Professional Documents
Culture Documents
C06-Kieu Con Tro-Final
C06-Kieu Con Tro-Final
C06-Kieu Con Tro-Final
Cơ sở lập trình 2
1. Con trỏ và địa chỉ
Ví dụ:
float a=10.12;
Xác định một biến có tên a có kiểu float và có giá trị
10.12.
Máy cấp phát cho x một vùng nhớ gồm 4 byte liên
tiếp.
Địa chỉ của biến là số thứ tự của byte đầu tiên
Có nhiều kiểu địa chỉ khác nhau tương ứng với
các kiểu biến khác nhau.
Cơ sở lập trình 3
1. Con trỏ và địa chỉ
Cơ sở lập trình 4
2. Khai báo con trỏ
Cơ sở lập trình 6
Con trỏ NULL
Khái niệm
Con trỏ NULL là con trỏ không trỏ vào đâu cả.
Khác với con trỏ chưa được khởi tạo.
int n;
int *p1 = &n;
int *p2; // unreferenced local varialbe
int *p3 = NULL;
NULL
Cơ sở lập trình 7
Khởi tạo kiểu con trỏ
Khởi tạo
<tên biến con trỏ> = &<tên biến>;
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 địa chỉ của biến vào con trỏ (toán tử &)
Ví dụ
int a, b;
int *pa = &a, *pb;
pb = &b;
Cơ sở lập trình 8
Sử dụng con trỏ
Cơ sở lập trình 9
Sử dụng con trỏ (tt)
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;
}
Cơ sở lập trình 11
Các cách truyền đối số
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;
}
Cơ sở lập trình 12
Các cách truyền đối số
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;
}
Cơ sở lập trình 13
Một số lưu ý
Một số lưu ý
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.
Ví dụ:
int *pa; *pa = 1904;
Cơ sở lập trình 14
3. Con trỏ và mảng một chiều
0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… …
array
Cơ sở lập trình 15
Con trỏ và mảng một chiều
… 0B 00 00 00 …
parray
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… …
array
Cơ sở lập trình 16
Phép toán số học trên con trỏ
p = array
+2
+1
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… …
int array[3];
Cơ sở lập trình 17
Phép toán số học trên con trỏ
p = &array[2]
–2
–1
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… …
int array[3];
Cơ sở lập trình 18
Phép toán số học trên con trỏ
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… …
int array[3];
Cơ sở lập trình 19
Phép toán số học trên con trỏ
Cơ sở lập trình 20
Con trỏ và mảng một chiều
* ( p + 2 )
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… …
int array[3];
Cơ sở lập trình 21
Con trỏ và mảng một chiều (tt)
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.
Cơ sở lập trình 24
4. Con trỏ và mảng 2 chiều
+1
0 1 2 3 4 5 6 7 8 9 10 11
int a[3][4]
Cơ sở lập trình 25
Con trỏ và mảng 2 chiều (tt)
(d, c) i ?
i = d*C + c
0 1 2 3 4 5 6 7 8 9 10 11
aDxC 0
1
i (d, c) ?
2
d=i/C
c=i%C
Cơ sở lập trình 27
Con trỏ và mảng 2 chiều (tt)
Bài toán
Sử dụng cấu trúc dữ liệu nào để lưu trữ thông tin
sau?
0 1 2 3 4 5 6 7
0 5 6
1 2 9 1 2 1 7 0 6
2 0 2
Giải pháp?
Cách 1: Mảng 2 chiều 3x8 (tốn bộ nhớ)
Cơ sở lập trình 29
Mảng con trỏ (tt)
… 1 5 6 …
28 29 2A 2B 2C 2D 2E 2F
… 2 9 1 2 1 7 0 6 …
3A 3B 3C
0 2 …
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
… 19 00 00 00 28 00 00 00 3A 00 00 00 …
array
Cơ sở lập trình 30
Mảng con trỏ (tt)
Cú pháp
<Kiểu dữ liệu> *Tên mảng con trỏ [số phần tủ];
Ví dụ: Chương trình giải bài toán mở đầu
int a[200],n,m;
int sl[20]; //Chua so luong phan tu cua moi mang
int *p[20]; //Mang cac con tro
void nhap()
{ int i,j=0;
printf("Nhap so mang: "); scanf("%d",&m);
for (i=0;i<m;i++)
{ printf("Nhap so phan tu cua mang: "); scanf("%d",&n);
p[i]=a+j;
for(int k=0;k<n;k++)
{ printf("a[%d]= ",k);
scanf("%d",a+j); j++; }
sl[i]=n;
}
}
Cơ sở lập trình
Mảng con trỏ (tt)
void xuat()
{ int i,j;
for(i=0;i<m;i++)
{
for (j=0;j<sl[i];j++)
printf("%d ",*((p[i])+j));
printf("\n");
}
}
main()
{
nhap();
xuat();
getch();
}
Cơ sở lập trình
6. Con trỏ hàm (tự đọc)
Ví dụ
// Con trỏ đến hàm nhận đối số int, trả về int
int (*ptof1)(int x);
Cơ sở lập trình
Con trỏ hàm (tt)
Cơ sở lập trình
Con trỏ hàm (tt)
Cơ sở lập trình
Con trỏ hàm (tt)
tinhtoan = Cong;
int kq1 = (*tinhtoan)(1, 2); // Chính quy
int kq2 = tinhtoan(1, 2); // Ngắn gọn
Cơ sở lập trình
Con trỏ hàm (tt)
main()
{
int (*pheptoan)(int, int) = &Cong;
int kq1 = TinhToan(1, 2, pheptoan);
int kq2 = TinhToan(1, 2, &Tru);
}
Cơ sở lập trình
Con trỏ hàm (tt)
main()
{
int (*pheptoan)(int, int) = NULL;
pheptoan = LayPhepToan(‘+’);
int kq2 = pheptoan(1, 2, &Tru);
}
Cơ sở lập trình
Con trỏ hàm (tt)
main()
{
PhepToan pheptoan = NULL;
pheptoan = LayPhepToan(‘+’);
int kq2 = pheptoan(1, 2, &Tru);
}
Cơ sở lập trình
Con trỏ hàm (tt)
Cơ sở lập trình
Con trỏ hàm (tt)
Lưu ý
Không được quên dấu () khi khai báo con trỏ hàm
int (*PhepToan)(int x, int y);
int *PhepToan(int x, int y);
Có thể bỏ tên biến tham số trong khai báo con trỏ
hàm
int (*PhepToan)(int x, int y);
int (*PhepToan)(int, int);
Cơ sở lập trình
7. Cấp phát bộ nhớ động
Biến tĩnh:
Ví dụ: int, float, mảng…
Là các biến được xác định khi mô tả kiểu, địa chỉ
của các biến được xác định ngay khi thực hiện
chương trình;
Thời gian tồn tại cùng với thời gian tồn tại của khối
chương trình chứa khai báo
Biến động:
Được tạo ra lúc chạy chương trình theo yêu cầu
Biến động không có tên
Truy nhập thông qua các biến con trỏ (là biến tĩnh,
chứa địa chỉ của các biến động)
Cơ sở lập trình
Cấp phát bộ nhớ động
Cơ sở lập trình
Cấp phát bộ nhớ động (tt)
Cơ sở lập trình
Ví dụ cấp phát bộ nhớ động