Trường Đại Học Công Nghiệp TP. HCM Khoa Công Nghệ Thông Tin
CHƯƠNG 3: KIỂU CON TRỎ(p2)
Võ Quang Hoàng Khang
Email: vqhkhang@gmail.com
1
&
VC
Nội dung
1
BB
Cấp phát bộ nhớ động
2
Con trỏ và mảng một chiều
3
Con trỏ và cấu trúc
4
Bài tập – Kiểm tra
22
&
VC
Cấp phát bộ nhớ tĩnh và động
BB
Cấp phát tĩnh (static memory allocation) Khai báo biến, cấu trúc, mảng, … Bắt buộc phải biết trước cần bao nhiều bộ nhớ lưu trữ tốn bộ nhớ, không thay đổi được kích thước, …
Cấp phát động (dynamic memory allocation)
Cần bao nhiêu cấp phát bấy nhiêu. Có thể giải phóng nếu không cần sử dụng.
33
&
VC
Cấp phát bộ nhớ động
BB
Thuộc thư viện hoặc
malloc calloc free
Trong C++ new delete
44
&
VC
Cấp phát bộ nhớ động
BB
void *malloc(size_t size)
Cấp phát một vùng nhớ size (bytes)
Con trỏ đến vùng nhớ được cấp phát NULL nếu không đủ bộ nhớ
int *p = (int *)malloc(10*sizeof(int)); if (p == NULL)
printf(“Không đủ bộ nhớ! ”);
55
&
VC
Cấp phát bộ nhớ động
BB
void *calloc(size_t num, size_t size)
Cấp phát vùng nhớ gồm num phần tử, mỗi phần tử kích thước size (bytes)
Con trỏ đến vùng nhớ được cấp phát NULL nếu không đủ bộ nhớ
int *p = (int *)calloc(10, sizeof(int)); if (p == NULL)
printf(“Không đủ bộ nhớ! ”);
66
&
VC
Cấp phát bộ nhớ động
BB
void *free(void *ptr)
Giải phóng vùng nhớ do ptr trỏ đến, được cấp bởi các hàm malloc(), calloc(). Nếu ptr là NULL thì không làm gì cả.
Không có
int *p = (int *)malloc(10*sizeof(int)); free(p);
77
&
VC
Cấp phát bộ nhớ động
BB
= new [size]
Cấp phát vùng nhớ có kích thước
sizeof(
Con trỏ đến vùng nhớ được cấp phát NULL nếu không đủ bộ nhớ
int *a1 = (int *)malloc(sizeof(int)); int *a2 = new int; int *p1 = (int *)malloc(10*sizeof(int)); int *p2 = new int[10];
88
&
VC
Cấp phát bộ nhớ động
BB
delete []
Giải phóng vùng nhớ do
Không có!
int *a = new int; delete a; int *p = new int[10]; delete []p;
99
&
VC
Cấp phát bộ nhớ động
BB
Lưu ý
Cấp phát bằng malloc, calloc thì giải phóng bằng free, cấp phát bằng new thì giải phóng bằng delete.
Cấp phát bằng new thì giải phóng bằng
delete, cấp phát mảng bằng new [] thì giải phóng bằng delete [].
1010
&
VC
Con trỏ và mảng một chiều
BB
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
…
…
1111
array
&
VC
Con trỏ và mảng một chiều
BB
Con trỏ đến mảng một chiều
int array[3], *parray;
parray = array; parray = &array[0];
// Cách 1 // 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
…
…
1212
array
&
VC
Phép toán số học trên con trỏ
BB
Phép cộng (tăng)
+ n + n * sizeof()
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
…
…
1313
int array[3];
&
VC
Phép toán số học trên con trỏ
BB
Phép trừ (giảm)
– n – n * sizeof()
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
…
…
1414
int array[3];
&
VC
Phép toán số học trên con trỏ
BB
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: * / %
1515
&
VC
Con trỏ và mảng một chiều
BB
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
…
…
1616
int array[3];
&
VC
Con trỏ và mảng một chiều
BB
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
}
&a[i] (a + i) (p + i) &p[i]
1717
&
VC
Con trỏ và mảng một chiều
BB
Ví dụ xuất mảng
void main()
{
// hoặc pa = &a[0];
int a[10], n = 10, *pa;
pa = a;
…
for (int i = 0; i
}
a[i] *(a + i) *(p + i) p[i]
1818
&
VC
Con trỏ và mảng một chiều
BB
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()
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ó.
1919
&
VC
Con trỏ cấu trúc
BB
Truy xuất bằng 2 cách
->
(*).
Ví dụ
struct PHANSO
{
int tu, mau;
// ps2 là con
};
PHANSO ps1, *ps2 = &ps1;
trỏ
2020
ps1.tu = 1; ps1.mau = 2;
ps2->tu = 1; ps2->mau = 2;
(*ps2).tu = 1; (*ps2).mau = 2;
&
VC
Con trỏ cấu trúc
BB
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
2121
&
VC
Bài tập
BB
Sử dụng con trỏ để làm lại các bài tập về mảng
một chiều.
2222
&
VC
Bài tập mẫu – Nhập mảng
BB
void NhapM(int *a,int n)
{
for(int i=0;i>*(a+i);
}
2323
&
VC
Bài tập mẫu – Xuất mảng
BB
void XuatM(int *a,int n)
{
for(int i=0;i
cout<<*(a+i)<<"\t";
cout<<"\n";
}
2424
&
VC
Bài tập mẫu – main
BB
int main()
{
int *a,n;
cout<<"Nhap so phan tu:";
cin>>n;
a=new int[n];
NhapM(a,n);
cout<<"\nMang da nhap:\n";
XuatM(a,n);
return 0;
2525
}
} &a[i] (a + i) (p + i) &p[i]
1717
&
VC
Con trỏ và mảng một chiều
BB
Ví dụ xuất mảng
void main() {
// hoặc pa = &a[0];
int a[10], n = 10, *pa;
pa = a;
…
for (int i = 0; i
}
a[i] *(a + i) *(p + i) p[i]
1818
&
VC
Con trỏ và mảng một chiều
BB
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()
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ó.
1919
&
VC
Con trỏ cấu trúc
BB
Truy xuất bằng 2 cách
->
(*).
Ví dụ
struct PHANSO
{
int tu, mau;
// ps2 là con
};
PHANSO ps1, *ps2 = &ps1;
trỏ
2020
ps1.tu = 1; ps1.mau = 2;
ps2->tu = 1; ps2->mau = 2;
(*ps2).tu = 1; (*ps2).mau = 2;
&
VC
Con trỏ cấu trúc
BB
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
2121
&
VC
Bài tập
BB
Sử dụng con trỏ để làm lại các bài tập về mảng
một chiều.
2222
&
VC
Bài tập mẫu – Nhập mảng
BB
void NhapM(int *a,int n)
{
for(int i=0;i>*(a+i);
}
2323
&
VC
Bài tập mẫu – Xuất mảng
BB
void XuatM(int *a,int n)
{
for(int i=0;i
cout<<*(a+i)<<"\t";
cout<<"\n";
}
2424
&
VC
Bài tập mẫu – main
BB
int main()
{
int *a,n;
cout<<"Nhap so phan tu:";
cin>>n;
a=new int[n];
NhapM(a,n);
cout<<"\nMang da nhap:\n";
XuatM(a,n);
return 0;
2525
}
} a[i] *(a + i) *(p + i) p[i]
1818
&
VC
Con trỏ và mảng một chiều
BB
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()
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ó.
1919
&
VC
Con trỏ cấu trúc
BB
Truy xuất bằng 2 cách
->
(*).
Ví dụ
struct PHANSO {
int tu, mau;
// ps2 là con
}; PHANSO ps1, *ps2 = &ps1; trỏ
2020
ps1.tu = 1; ps1.mau = 2; ps2->tu = 1; ps2->mau = 2; (*ps2).tu = 1; (*ps2).mau = 2;
&
VC
Con trỏ cấu trúc
BB
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
2121
&
VC
Bài tập
BB
Sử dụng con trỏ để làm lại các bài tập về mảng một chiều.
2222
&
VC
Bài tập mẫu – Nhập mảng
BB
void NhapM(int *a,int n) {
for(int i=0;i>*(a+i);
}
2323
&
VC
Bài tập mẫu – Xuất mảng
BB
void XuatM(int *a,int n) {
for(int i=0;i
cout<<*(a+i)<<"\t";
cout<<"\n";
}
2424
&
VC
Bài tập mẫu – main
BB
int main()
{
int *a,n;
cout<<"Nhap so phan tu:";
cin>>n;
a=new int[n];
NhapM(a,n);
cout<<"\nMang da nhap:\n";
XuatM(a,n);
return 0;
2525
}
cout<<*(a+i)<<"\t";
cout<<"\n";
}
2424
&
VC
Bài tập mẫu – main
BB
int main() {
int *a,n; cout<<"Nhap so phan tu:"; cin>>n; a=new int[n]; NhapM(a,n); cout<<"\nMang da nhap:\n"; XuatM(a,n); return 0;
2525

