Bài giảng Kỹ thuật lập trình - Chương 7: Con trỏ - Lê Thành Sách

Nội dung
n Tổ chức bộ nhớ thực thi
n Ứng dụng của con trỏ
n Mô hình của con trỏ
n Toán tử &
n Khai báo trỏ
n Toán tử *
n Các phép toán trên con trỏ
n Con trỏ và mảng
n Cấp phát bộ nhớ động
n Con trỏ và cấu trúc, toán tử ->
n Các chủ đề nâng cao với con trỏ
n Thứ tự đánh giá * và ++, --
n Con trỏ và const
n Con trỏ đến con trỏ
n Con trỏ void 
pdf 51 trang xuanthi 27/12/2022 3220
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Kỹ thuật lập trình - Chương 7: Con trỏ - Lê Thành Sách", để tải tài liệu gốc về máy hãy click vào nút Download ở trên.

File đính kèm:

  • pdfbai_giang_ky_thuat_lap_trinh_chuong_7_con_tro_le_thanh_sach.pdf

Nội dung text: Bài giảng Kỹ thuật lập trình - Chương 7: Con trỏ - Lê Thành Sách

  1. Nội dung n Tổ chức bộ nhớ thực thi n Ứng dụng của con trỏ n Mô hình của con trỏ n Toán tử & n Khai báo trỏ n Toán tử * n Các phép toán trên con trỏ n Con trỏ và mảng n Cấp phát bộ nhớ động n Con trỏ và cấu trúc, toán tử -> n Các chủ đề nâng cao với con trỏ n Thứ tự đánh giá * và ++, n Con trỏ và const n Con trỏ đến con trỏ n Con trỏ void Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 2 © 2016
  2. Tổ chức bộ nhớ thực thi n Vùng “text” n Chứa mã thực thi của chương trình n Vùng này chỉ đọc n Vùng này có thể dùng chung trong trường hợp chương trình thực thi thường xuyên (Nguồn: Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 4 © 2016
  3. Tổ chức bộ nhớ thực thi n Vùng “Data” n Gồm: n Dữ liệu được khởi động (bởi người lập trình) n Biến toàn cục n Biến tĩnh (static) n Vùng này gồm hai vùng con: n Chỉ đọc n Ví dụ: Hằng chuỗi n Đọc/ghi n Các biến static và global không hằng (Nguồn: Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 6 © 2016
  4. Tổ chức bộ nhớ thực thi n Vùng “HEAP” n Chứa bộ nhớ xin cấp phát động bởi người lập trình n Liên quan đến Kiểu dữ liệu con trỏ nói trong chương này (Nguồn: Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 8 © 2016
  5. Ứng dụng của con trỏ n Mảng trong C n Phải biết trước số lượng phần tử tại thời điểm viết chương trình n Do đó, cần phải khai báo một số lượng lớn các ô nhớ để sẵn. Tuy nhiên, tại một thời điểm nào đó, chương trình có thể sẽ sử dụng ít hơn rất nhiều à lãng phí n Yêu cầu: Có thể nào dùng mảng với số lượng phần tử chỉ cần biết lúc chương trình đang chạy? n => Cần con trỏ Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 10 © 2016
  6. Mô hình của con trỏ Biến a: là biến có kiểu nào đó bất kỳ Ô nhớ bắt đầu của a có địa chỉ là: (ví dụ) 0x1234 FFFF 0x1234 FFFF Biến p: là con trỏ Chứa địa chỉ của biến x, nghĩa là giá trị 0x1234 FFFF Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 12 © 2016
  7. Toán tử & n Con trỏ lưu trữ địa chỉ của một ô nhớ (biến) khác è Bằng cách nào lấy địa chỉ của một biến hay ô nhớ để gán cho biến con trỏ Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 14 © 2016
  8. Toán tử & n Toán tử & trả về địa chỉ của một biến n Ví dụ #include #include int main(){ int a = 100; printf("%d\n", a); In ra giá trị của a printf("%p\n", &a); In ra địa chỉ của a system("pause"); return 0; } Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 16 © 2016
  9. Khai báo con trỏ Cú pháp * ; * = 0; * = & ; : Phải có kiểu , hoặc có kiểu chuyển đổi qua được 0: Hằng số, gọi là NULL Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 18 © 2016
  10. Toán tử * n Toán tử * lấy giá trị (tham khảo) tại một địa chỉ n Toán tử & lấy địa chỉ của biến Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 20 © 2016
  11. Các phép toán trên con trỏ n Tăng và Giảm: ++, n Cộng và trừ: +, - n Cộng và trừ kết hợp gán: +=, -= n So sanh: ==, != Gọi p là con trỏ có kiểu T: T *p; Các phép cộng và trừ: làm con trỏ p tăng hay giảm một bội số của kích thước kiểu T. Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 22 © 2016
  12. Con trỏ và mảng #include Có thể gán con trỏ #include mảng vào con trỏ int main(){ => int a[5]; A và p có giữ cùng int *p = a; địa chỉ: địa chỉ của ô đầu tiên trên mảng printf("a =%p\n", a); printf("p =%p\n", p); system("pause"); return 0; } Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 24 © 2016
  13. Con trỏ và mảng n Con trỏ và mảng cũng có điểm khác nhau n Mảng: các phần tử của mảng nằm trên STACK của chương trình n Con trỏ: Các phần tử mảng con trỏ chỉ đến có thể trên STACK hay HEAP Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 26 © 2016
  14. Cấp phát bộ nhớ động n Hàm xin bộ nhớ n malloc n calloc n realloc n Hàm giải phóng bộ nhớ n free Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 28 © 2016
  15. Cấp phát bộ nhớ động malloc p1 = (int*)malloc(num*sizeof(int)); num: số con số int cần xin sizeof(int): kích thước của mỗi số nguyên. è num*sizeof(int): số bytes cần thiết để xin (Đối số truyền vào hàm malloc là số bytes bộ nhớ cần xin) Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 30 © 2016
  16. Cấp phát bộ nhớ động malloc #include #include int main(){ int num = 100; int *p1 = (int*)malloc(num*sizeof(int)); if(p1 == NULL){ printf("Xin khong duoc!\n"); exit(1); } else{ //Thuc hien cong viec tai day free(p1); } return 0; } Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 32 © 2016
  17. Cấp phát bộ nhớ động Ví dụ Khai báo biến con trỏ đến các kiểu + xin cấp phát bộ nhớ động typedef struct{ float x, y, z; } Point3D; int main(){ int num = 20; int *int_ptr = (int*)malloc(num*sizeof(int)); char *str = (char*)malloc(num*sizeof(char)); double *double_ptr = (double*)malloc(num*sizeof(double)); Point3D *p_ptr = (Point3D*)malloc(num*sizeof(Point3D)); //Su dung free(int_ptr); free(str); free(double_ptr); free(p_ptr); Giải phóng các vùng nhớ sau khi sử dụng return 0; } Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 34 © 2016
  18. Con trỏ và cấu trúc Truy cập biến thành viên cấu trúc qua con trỏ Ví dụ: gán các biến thành viên của cấu trúc Point3D (*p_ptr).x = 4.5f; (*p_ptr).y = 5.5f; (*p_ptr).z = 6.5f; p_ptr->x = 7.5f; p_ptr->y = 8.5f; p_ptr->z = 9.5f; p_ptr : Ô nhớ (biến) chứa địa chỉ của một cấu trúc Point3D (*p_ptr) : Nghĩa là vùng nhớ của cấu trúc Point3D (*p_ptr).x : Nghĩa là vùng nhớ chứa biến x của cấu trúc Point3D p_ptr->x : Nghĩa là vùng nhớ chứa biến x của cấu trúc Point3D, truy cập thông qua toán tử -> từ con trỏ p_ptr Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 36 © 2016
  19. Con trỏ và cấu trúc Chương trình minh hoạ # include # include typedef struct{ float x, y, z; } Point3D; int main(){ Point3D p = {1.5f, 2.5f, 3.5f}; Point3D *p_ptr = (Point3D*)malloc(sizeof(Point3D)); (*p_ptr).x = 4.5f; (*p_ptr).y = 5.5f; (*p_ptr).z = 6.5f; p_ptr->x = 7.5f; p_ptr->y = 8.5f; p_ptr->z = 9.5f; printf("p = [%-4.1f, %-4.1f, %4.1f]\n", p.x, p.y, p.z); printf("*p_ptr = [%-4.1f, %-4.1f, %4.1f]\n", (*p_ptr).x, (*p_ptr).y, (*p_ptr).z); printf("*p_ptr = [%-4.1f, %-4.1f, %4.1f]\n", p_ptr->x, p_ptr->y, p_ptr->z); free(p_ptr); system("pause"); Trường Đại HọcreturnBách Khoa0; Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 38 © }2016
  20. Con trỏ và const int a = 20, b = 30, c = 40; ptr1: có thể thay đổi được. const int * ptr1 = &a; Giá trị mà ptr1 chỉ đến không thể //int const * ptr1 = &a; thay đổi được int* const ptr2 = &b; Ô nhớ ptr1 chỉ đến (Không thể thay đổi được thông qua ptr1) ptr1: Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 40 © 2016
  21. Con trỏ và const Các lỗi thông dụng Ptr3: là con trỏ hằng nhưng không được khởi động tương tự như cho ptr2 Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 42 © 2016
  22. Con trỏ và const Các lỗi thông dụng Con trỏ ptr2 là hằng số, nó chỉ nhận giá trị khởi động Sau đó, không thể làm ptr2 chỉ đến đối tượng nào khác Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 44 © 2016
  23. Con trỏ và const Các lỗi thông dụng -> OK -> LỖI ptr3: con trỏ bình thường, thay đổi được nó và giá trị nó chỉ đến Gán con trỏ ptr1 vào ptr3: khiến cho giá trị mà ptr1 chỉ đến có thể thay đổi được à bộ biên dich không cho phép. Vì nếu cho phép thì ý nghĩa của ptr1 không còn. Người lập trình luôn luôn có thể thay đổi nội dung mà ptr1 chỉ đến, bằng cáhch dùng con trỏ phụ. Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 46 © 2016
  24. Con trỏ đến con trỏ int x; int* px = &x; int ppx = &px; int ppx = &ppx; Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 48 © 2016
  25. Con trỏ void n void *ptr: là con trỏ chưa định kiểu n Có thể được ép kiểu về kiểu mong muốn n Như các hàm malloc và free n Con trỏ void giúp chương trình uyển chuyển, n Nhưng rủi ro đi kèm: bộ biên dịch không thể kiểm tra tương thích kiểu tại thời điểm biên dịch Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 50 © 2016