Bài giảng Kỹ thuật lập trình - Chương 07: Con trỏ - Nguyễn Thanh Tùng
nTổ chức bộ nhớ thực thi
nỨng dụng của con trỏ
nMô hình của con trỏ
nToán tử &
nKhai báo trỏ
nToán tử *
nCác phép toán trên con trỏ
nCon trỏ và mảng
nCấp phát bộ nhớ động
nCon trỏ và cấu trúc, toán tử ->
nCác chủ đề nâng cao với con trỏ
nThứ tự đánh giá * và ++, --
nCon trỏ và const
nCon trỏ đến con trỏ
nCon trỏ void
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 07: Con trỏ - Nguyễn Thanh Tùng", để 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:
- bai_giang_ky_thuat_lap_trinh_chuong_07_con_tro_nguyen_thanh.pptx
Nội dung text: Bài giảng Kỹ thuật lập trình - Chương 07: Con trỏ - Nguyễn Thanh Tùng
- 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
- Tổ chức bộ nhớ thực thi ◼ Khi chương trình được lên bộ nhớ để thực thi, hệ thống tổ chức bộ nhớ như hình vẽ (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
- Tổ chức bộ nhớ thực thi ◼ Vùng “Data” ◼ Gồm: ◼ Dữ liệu được khởi động (bởi người lập trình) ◼ Dữ liệu không được khởi động (bởi người lập trình) (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
- Tổ chức bộ nhớ thực thi ◼ Vùng “Data” ◼ Gồm: ◼ Dữ liệu được khởi động ◼ Dữ liệu không khởi động bởi người lập trình ◼ Biến toàn cục ◼ Biến tĩnh (static) ◼ Hệ thống khởi động về 0 (số) cho các biến không được người lập trình chủ động khởi độ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 8 © 2016
- Tổ chức bộ nhớ thực thi ◼ Vùng “STACK” ◼ Chứa ◼ Các biến được khai báo trong chương trình ◼ Thông tin mỗi lần gọi hàm (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 10 © 2016
- Ứng dụng của con trỏ ◼ Mảng trong C ◼ Khi thêm vào và lấy ra các phần tử trên mảng ◼ => cần phải dịch phải và trái nhiều phần tử → tốn nhiều thời gian ◼ Yêu cầu: Có cách tổ chức dữ liệu nào giúp các phép quản lý phần tử nói trên nhanh chóng ◼ => Sử dụng danh sách liên kết ◼ => Cần đế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 12 © 2016
- 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 Biến p: là con trỏ Chứa địa chỉ của biến x, nghĩa là giá trị 0x1234 FFFF Minh hoạ con trỏ bởi tên từ ô nhớ biến p CHỈ ĐẾN (point to) ô nhớ biến x 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
- Toán tử & ◼ 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ỏ ◼ Cách 1: Dùng toán tử & để lấy địa chỉ của một biến đang có ◼ Cách 2: Xin cấp phát bộ nhớ động (phần sau) 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
- Toán tử & ◼ Toán tử & trả về địa chỉ của một biến ◼ Ví dụ #include #include typedef struct sPoint3D{float x, y, z;} Point3D; int main(){ Point3D p1 = {1.0f, 2.0f, 3.0f}; printf("%-5.1f\n", p1.x); In ra giá trị của p1.x printf("%p\n", &p1); printf("%p\n", &p1.x); In ra địa chỉ của p1 printf("%p\n", &p1.y); In ra địa chỉ của p1.x printf("%p\n", &p1.z); system("pause"); In ra địa chỉ của p1.y return 0; In ra địa chỉ của p1.z } 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
- Khai báo con trỏ Cú pháp a: là số nguyên int a; p1: con trỏ đến số nguyên, giá trị chưa xác định int *p1; p2: con trỏ đến số nguyên, giá trị là NULL int *p2 = 0; p3: con trỏ đến số nguyên, giá trị chính là địa chỉ int *p3 = &a; của số nhớ a double d; double *pd1; double *pd2 = 0; double *pd3 = &d; f: là số float float f; pf1: con trỏ đến số float, giá trị chưa xác định float *pf1; pf2: con trỏ đến số float, giá trị là NULL float *pf2 = 0; pf3: con trỏ đến số float, giá trị chính là địa chỉ float *pf3 = &d; của số nhớ f Point3D p1 = {1.0f, 2.0f, 3.0f}; Point3D *pp1; Point3D *pp2 = 0; Point3D *pp3 = &p1; 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
- Toán tử * #include #include int main(){ int a = 100; printf("a=%d\n", a); printf("*&a=%d\n", *&a); printf("*&*&a=%d\n", *&*&a); printf("*&*&*&a=%d\n", *&*&*&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 22 © 2016
- Con trỏ và mảng ◼ Con trỏ và mảng có nhiều điểm giống nhau ◼ Con trỏ & mảng: giữ địa chỉ của ô nhớ ◼ Con trỏ: giữa địa chỉ của ô nhớ nào đó (của biến khác, của bộ nhớ động) ◼ Mảng: giữ địa chỉ của phần tử đầu tiên ◼ => có thể gán mảng vào con trỏ ◼ Tuy nhiên, gán con trỏ vào mảng là không đượ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 24 © 2016
- Con trỏ và mảng ◼ Con trỏ và mảng có nhiều điểm giống nhau ◼ Có cùng cách truỳ cập các ô nhớ ◼ Dùng toán tử [ ] ◼ Dùng toán tử * và + int a[5]; int *p = a; int id = 2; a[id] = 100; Giống nhau p[id] = 100; *(a + id) = 100; *(p + id) = 100; 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
- Cấp phát bộ nhớ động ◼ Giúp người lập trình tạo ra mảng động. Không cần xác định số lượng phần tử của mảng động tại thời điểm biên dịch như mảng tĩnh ◼ Mảng động sẽ được cấp phát trên HEAP Mỗi khi xin cấp phát bộ nhớ CẦN PHẢI giải phóng vùng nhớ xin được khi dùng xong 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
- Cấp phát bộ nhớ động malloc #include #include typedef struct sPoint3D{float x, y, z;} Point3D; int main(){ int *p1; float *p2; Các biến con trỏ Point3D *p3; int num = 100; Xin cấp bộ nhớ p1 = (int*)malloc(num*sizeof(int)); p2 = (float*)malloc(num*sizeof(float)); p3 = (Point3D*)malloc(num*sizeof(Point3D)); free(p1); free(p2); free(p3); Giải phóng bộ nhớ 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 30 © 2016
- Cấp phát bộ nhớ động malloc p1 = (int*)malloc(num*sizeof(int)); Hàm malloc trả về kiểu void* (kiểu vô định). Cần ép vào kiểu của bên tay trái p1: kiểu int* ➔ ép vào int* bằng (int*) 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
- Cấp phát bộ nhớ động malloc int *p1 = (int*)malloc(num*sizeof(int)); if(p1 == NULL){ } else { } Hàm malloc trả về NULL nếu không xin được. Lúc đó, không thể dùng bộ nhớ được! Do đó, LUÔN LUÔN kiểm tra xem malloc có trả về NULL hay không 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
- Con trỏ và cấu trúc Khai báo typedef struct{ float x, y, z; (1) Định nghĩa kiểu cấu trúc: Point3D } Point3D; Point3D *p_ptr = (Point3D*)malloc(sizeof(Point3D)); // (4) Sử dụng free(p_ptr); (2) Khai báo con trỏ đến một mảng (3) Xin cấp phát bộ nhớ trên HEAP, p_ptr: giữ địa chỉ của ô nhớ đầu tiên trong (5) Giải phóng vùng nhớ vùng được cấp 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
- 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; Tổng quát: -> Như: p_ptr->x Trường Đại Học Bách Khoa Lập trình C/C++ Trung Tâm Kỹ Thuật Điện Toán 38 © 2016
- Thứ tự các phép toán *, ++ và ❖*p++ // *(p++) ❖*++p // *(++p) ❖++*p // ++(*p) ❖(*p)++ // Tăng vùng nhớ do con trỏ p chỉ đến Khi nghi ngờ, hoặc không nhớ hãy dùng toán tử () để phân giải độ ưu tiê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 40 © 2016
- Con trỏ và const int a = 20, b = 30, c = 40; ptr2: Không thể thay đổi được giá trị của ptr2 = không thể làm ptr2 chỉ đến ô nhớ nào khác sau const int * ptr1 = &a; dòng này. int* const ptr2 = &b; Giá trị mà ptr2 chỉ đến có thể thay đổi được qua tr. Ô nhớ ptr2 chỉ đến (Không thể thay ptr2: đổi được 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
- Con trỏ và const Các lỗi thông dụng Giá trị mà ptr1 chỉ đến không thay đổi được qua con trỏ ptr1. Do đó, nó không thể nằm bên trái biểu thức gá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 44 © 2016
- Con trỏ và const Các lỗi thông dụng 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
- Con trỏ và const Các lỗi thông dụng -> LỖI -> OK ptr2: không thể thay đổi giá trị đượ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 48 © 2016
- Con trỏ đến con trỏ int x; 10 x = 10; int* px = &x; *px = 10; int ppx = &px; ppx = 10; int ppx = &ppx; pppx = 10; 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
- Bài tập ◼ Hiện thực lại các bài tập về array nhưng dữ liệu các array nằm trên bộ nhớ 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 52 © 2016