You are on page 1of 32

Trường Đại học Khoa học Tự nhiên

Khoa Công nghệ thông tin


Bộ môn Tin học cơ sở

TIN HỌC CƠ SỞ 2
Đặng Bình Phương
dbphuong@fit.hcmuns.edu.vn

DỮ LIỆU KIỂU CON TRỎ

1
&
VC
BB
Nội dung

1 Khái niệm và cách sử dụng

2 Các cách truyền đối số cho hàm

3 Con trỏ và mảng một chiều

4 Con trỏ và cấu trúc

Tin học cơ sở 2 - Đặng Bình Phương 2


&
VC
BB
Kiến trúc máy tính

Bộ nhớ máy tính


 Bộ nhớ RAM chứa rất nhiều ô nhớ, mỗi ô nhớ có
kích thước 1 byte.
 RAM dùng để chứa một phần hệ điều hành, các
lệnh chương trình, các dữ liệu…
 Mỗi ô nhớ có địa chỉ duy nhất và địa chỉ này
được đánh số từ 0 trở đi.
 Ví dụ
• RAM 512MB được đánh địa chỉ từ 0 đến 229 – 1
• RAM 2GB được đánh địa chỉ từ 0 đến 231 – 1

Tin học cơ sở 2 - Đặng Bình Phương 3


&
VC
BB
Khai báo biến trong C

 Quy trình xử lý của trình biên dịch


 Dành riêng một vùng nhớ với địa chỉ duy
nhất để lưu biến đó.
 Liên kết địa chỉ ô nhớ đó với tên biến.
 Khi gọi tên biến, nó sẽ truy xuất tự động
đến ô nhớ đã liên kết với tên biến.
 Ví dụ: int a = 0x1234; // Giả sử địa chỉ
0x0B
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… 34 12 00 00 …

a Tin học cơ sở 2 - Đặng Bình Phương 4


&
VC
BB
Khái niệm con trỏ

 Khái niệm
 Địa chỉ của biến là một con số.
 Ta có thể tạo biến khác để lưu địa chỉ
của biến này  Con trỏ.

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… 34 12 00 00 0B 00 00 00 …

a pa Tin học cơ sở 2 - Đặng Bình Phương 5


&
VC
BB
Khai báo con trỏ

Khai báo
 Giống như mọi biến khác, biến con trỏ muốn sử
dụng cũng cần phải được khai báo

<kiểu dữ liệu> *<tên biến con trỏ>;


Ví dụ

char
 ch1*ch1, *ch2;
và ch2 là biến con trỏ, trỏ tới vùng nhớ kiểu
int *p1, p2;
char (1 byte).
 p1 là biến con trỏ, trỏ tới vùng nhớ kiểu int (4
bytes) còn p2 là biến kiểu int bình thường.

Tin học cơ sở 2 - Đặng Bình Phương 6


&
VC
BB
Khai báo con trỏ

 Sử dụng từ khóa typedef


typedef <kiểu dữ liệu> *<tên kiểu con trỏ>;

<tên kiểu con trỏ> <tên biến con trỏ>;


 Ví dụ
typedef int *pint;
int *p1;
pint p2, p3;

 Lưu ý khi khai báo kiểu dữ liệu mới


 Giảm bối rối khi mới tiếp xúc với con trỏ.
 Nhưng dễ nhầm lẫn với biến thường.
Tin học cơ sở 2 - Đặng Bình Phương 7
&
VC
BB
Con trỏ NULL

 Khái niệm
 Con trỏ NULL là con trỏ không trỏ và đâu
cả.
 Khác
int n; với con trỏ chưa được khởi tạo.
int *p1 = &n;
int *p2; // unreferenced local varialbe
int *p3 = NULL;

NULL

Tin học cơ sở 2 - Đặng Bình Phương 8


&
VC
BB
Khởi tạo kiểu con trỏ

 Khởi tạo
 Khi mới khai báo, biến con trỏ được đặt ở
địa chỉ nào đó (không biết trước).
 chứa giá trị không xác định
 trỏ đến vùng nhớ không biết
trước.
 Đặt
<tên địacon
biến chỉtrỏ>
của= biến
&<tênvào con trỏ (toán tử
biến>;
&)
int a, b;
 Ví
intdụ
*pa = &a, *pb;
pb = &b;
Tin học cơ sở 2 - Đặng Bình Phương 9
&
VC
BB
Sử dụng con trỏ

 Truy xuất đến ô nhớ mà con trỏ trỏ đến


 Con trỏ chứa một số nguyên chỉ địa chỉ.
 Vùng nhớ mà nó trỏ đến, sử dụng toán
tử *.
 Ví
intdụ
a = 5, *pa = &a;
printf(“%d\n”, pa); // Giá trị biến pa
printf(“%d\n”, *pa); // Giá trị vùng nhớ pa trỏ đến
printf(“%d\n”, &pa); // Địa chỉ biến pa

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… 05 00 00 00 0B 00 00 00 …

10
a pa Tin học cơ sở 2 - Đặng Bình Phương
&
VC
BB
Kích thước của con trỏ

 Kích thước của con trỏ


char *p1;
int *p2;
float *p3;
double *p4;

 Con trỏ chỉ lưu địa chỉ nên kích thước
của mọi con trỏ là như nhau:
• Môi trường MD-DOS (16 bit): 2 bytes (64KB)
• Môi trường Windows (32 bit): 4 bytes (4GB)

Tin học cơ sở 2 - Đặng Bình Phương 11


&
VC
BB
Các cách truyền đối số

 Truyền giá trị (tham trị)


#include <stdio.h>

void hoanvi(int x, int y);

void main()
{
int a = 5; b = 6;
hoanvi(a, b);
printf(“a = %d, b = %d”, a, b);
}
void hoanvi(int x, int y)
{
int t = x; x = y; y = t;
}
Tin học cơ sở 2 - Đặng Bình Phương 12
&
VC
BB
Truyền giá trị (tham trị)
int x int y

18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25

… 05 00 00 00 06 00 00 00 …

int t = x;
hoanvi int x int y x = y;
y = t;

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… 05 00 00 00 06 00 00 00 …

int a = 5 int b = 6 Tin học cơ sở 2 - Đặng Bình Phương 13


&
VC
BB
Các cách truyền đối số

 Truyền địa chỉ (con trỏ)


#include <stdio.h>

void hoanvi(int *x, int *y);

void main()
{
int a = 2912; b = 1706;
hoanvi(&a, &b);
printf(“a = %d, b = %d”, a, b);
}
void hoanvi(int *x, int *y)
{
int t = *x; *x = *y; *y = t;
}
Tin học cơ sở 2 - Đặng Bình Phương 14
&
VC
BB
Truyền địa chỉ (con trỏ)
int *x int *y

18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25

… 0B 00 00 00 0F 00 00 00 …

int t = *x;
hoanvi int *x int *y *x = *y;
*y = *t;

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… 05 00 00 00 06 00 00 00 …

int a = 5 int b = 6 Tin học cơ sở 2 - Đặng Bình Phương 15


&
VC
BB
Các cách truyền đối số

 Truyền tham chiếu (C++)


#include <stdio.h>

void hoanvi(int &x, int &y);

void main()
{
int a = 2912; b = 1706;
hoanvi(a, b);
printf(“a = %d, b = %d”, a, b);
}
void hoanvi(int &x, int &y)
{
int t = x; x = y; y = t;
}
Tin học cơ sở 2 - Đặng Bình Phương 16
&
VC
BB
Truyền tham chiếu (C++)

int t = x;
hoanvi int &x int &y x = y;
y = t;

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… 05 00 00 00 06 00 00 00 …

int a = 5 int b = 6 Tin học cơ sở 2 - Đặng Bình Phương 17


&
VC
BB
Một số lưu ý

 Một số lưu ý
 Con trỏ là khái niệm quan trọng và khó
nhất trong C. Mức độ thành thạo C được
đánh giá qua mức độ sử dụng con trỏ.
 Nắm rõ quy tắc sau, ví dụ int a, *pa = &a;
• *pa và a đều chỉ nội dung của biến a.
• pa và &a đều chỉ địa chỉ của biến a.
 Không nên sử dụng con trỏ khi chưa được
khởi tạo. Kết quả sẽ không lường trước
được.
int *pa; *pa = 1904;

Tin học cơ sở 2 - Đặng Bình Phương 18


&
VC
BB
Con trỏ và mảng một chiều

 Mảng một chiều


int array[3];
 Tên mảng array là một hằng con trỏ
 không thể thay đổi giá trị của
hằng này.
 array là địa chỉ đầu tiên của mảng
array == &array[0]
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… …

array Tin học cơ sở 2 - Đặng Bình Phương 19


&
VC
BB
Con trỏ và mảng một chiều

 Con trỏ đến mảng một chiều


int array[3], *parray;

parray = array; // Cách 1


parray = &array[0]; // Cách 2
18 19 1A 1B 1C 1D 1E 1F

… 0B 00 00 00 …
parray
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… …

array Tin học cơ sở 2 - Đặng Bình Phương 20


&
VC
BB
Phép toán số học trên con trỏ

 Phép cộng (tăng)


 + n  + n * sizeof(<kiểu dữ liệu>)
 Có thể sử dụng toán tử gộp += hoặc ++
p = array
+2

+1

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… …

int array[3]; Tin học cơ sở 2 - Đặng Bình Phương 21


&
VC
BB
Phép toán số học trên con trỏ

 Phép trừ (giảm)


 – n  – n * sizeof(<kiểu dữ liệu>)
 Có thể sử dụng toán tử gộp –= hoặc – –
p = &array[2]
–2

–1

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… …

int array[3]; Tin học cơ sở 2 - Đặng Bình Phương 22


&
VC
BB
Phép toán số học trên con trỏ

 Phép toán tính khoảng cách giữa 2 con trỏ


 <kiểu dữ liệu> *p1, *p2;
 p1 – p2 cho ta khoảng cách (theo số
phần tử) giữa hai con trỏ (cùng kiểu)
p1 = array p2 = &array[2]
p1 – p2= (0B – 13)/sizeof(int) = –2

p2 – p1= (13 – 0B)/sizeof(int) = +2

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… …

int array[3]; Tin học cơ sở 2 - Đặng Bình Phương 23


&
VC
BB
Phép toán số học trên con trỏ

 Các phép toán khác


 Phép so sánh: So sánh địa chỉ giữa hai
con trỏ (thứ tự ô nhớ)
• == !=
• > >=
• < <=
 Không thể thực hiện các phép toán: * /
%

Tin học cơ sở 2 - Đặng Bình Phương 24


&
VC
BB
Con trỏ và mảng một chiều

 Truy xuất đến phần tử thứ n của mảng


(không sử dụng biến mảng)
 array[n] == p[n] == *(p + n)

* ( p + 2 )

0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17

… …

int array[3]; Tin học cơ sở 2 - Đặng Bình Phương 25


&
VC
BB
Con trỏ và mảng một chiều

 Ví dụ nhập mảng
void main()
{
int a[10], n = 10, *pa;
pa = a; // hoặc pa = &a[0];

for (int i = 0; i<n; i++)


scanf(“%d”, &a[i]);
scanf(“%d”, &p[i]);
scanf(“%d”, a + i);
scanf(“%d”, p + i);
scanf(“%d”, a++);
scanf(“%d”, p++);
}
 &a[i]  (a + i)  (p + i)  &p[i]
Tin học cơ sở 2 - Đặng Bình Phương 26
&
VC
BB
Con trỏ và mảng một chiều

 Ví dụ xuất mảng
void main()
{
int a[10], n = 10, *pa;
pa = a; // hoặc pa = &a[0];

for (int i = 0; i<n; i++)
printf(“%d”, a[i]);
printf(“%d”, p[i]);
printf(“%d”, *(a + i));
printf(“%d”, *(p + i));
printf(“%d”, *(a++));
printf(“%d”, *(p++));
}
 a[i]  *(a + i)  *(p + i)  p[i]
Tin học cơ sở 2 - Đặng Bình Phương 27
&
VC
BB
Truyền mảng 1 chiều cho hàm

 Chú ý!
 Mảng một chiều truyền cho hàm là địa
chỉ của phần tử đầu tiên chứ không phải
toàn mảng.
xuất int a[3] int n

int a[] int *a

10 11 13 14 15 16 17 18 19 20 21 22 23 24

… …

int array[3]; Tin học cơ sở 2 - Đặng Bình Phương 28


&
VC
BB
Con trỏ và mảng một chiều

 Ví dụ
void xuat(int a[10], int n)
{
for (int i = 0; i<n; i++)
printf(“%d”, *(a++)); // OK
}

void main()
{
int a[10], n = 10;

for (int i = 0; i<n; i++)


printf(“%d”, *(a++)); // Lỗi
}
 Đối số mảng truyền cho hàm không phải hằng
con trỏ. Tin học cơ sở 2 - Đặng Bình Phương 29
&
VC
BB
Con trỏ và mảng một chiều

Lưu ý
 Không thực hiện các phép toán nhân, chia, lấy
phần dư.
 Tăng/giảm con trỏ n đơn vị có nghĩa là tăng/giảm
giá trị của nó n*sizeof(<kiểu dữ liệu mà nó trỏ
đến>)
 Không thể tăng/giảm biến mảng. Hãy gán một
con trỏ đến địa chỉ đầu của mảng và tăng/giảm
nó.
 Đối số mảng một chiều truyền cho hàm là địa chỉ
phần tử đầu tiên của mảng.

Tin học cơ sở 2 - Đặng Bình Phương 30


&
VC
BB
Con trỏ cấu trúc

 Truy xuất bằng 2 cách


<tên biến con trỏ cấu trúc>-><tên thành phần>
(*<tên biến con trỏ cấu trúc>).<tên thành phần>

 Ví dụ
struct PHANSO
{
int tu, mau;
};
PHANSO ps1, *ps2 = &p1; // ps2 là con trỏ

ps1.tu = 1; ps1.mau = 2;
ps2->tu = 1; ps2->mau = 2;
(*ps2).tu = 1; (*ps2).mau = 2;
Tin học cơ sở 2 - Đặng Bình Phương 31
&
VC
BB
Con trỏ cấu trúc

 Gán hai cấu trúc


struct PHANSO
{
int tu, mau;
};
PHANSO ps1, *ps2;

ps1.tu = 1; ps1.mau = 2; // ps1 = 1/2

ps2 = &ps1;
ps2->tu = 3; ps2->mau = 4; // ps1 = 3/4

Tin học cơ sở 2 - Đặng Bình Phương 32

You might also like