Bài giảng Phương pháp lập trình - Chương 5: Con trỏ (Pointers) - Võ Quang Hoàng Khang

pdf 37 trang phuongnguyen 2241
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Phương pháp lập trình - Chương 5: Con trỏ (Pointers) - Võ Quang Hoàng Khang", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfbai_giang_phuong_phap_lap_trinh_chuong_5_con_tro_pointers_vo.pdf

Nội dung text: Bài giảng Phương pháp lập trình - Chương 5: Con trỏ (Pointers) - Võ Quang Hoàng Khang

  1. CHƯƠNG 5 CON TRỎ (Pointers)
  2. 1. Gi ớithii thiệu y Mộtcontrỏ là 1biếnchứamột địachỉ bộ nhớ. Địachỉ này là vị trí củamột đốitượng khác trong bộ nhớ. y Nếumộtbiếnchứa địachỉ củamộtbiếnkhác, biếnthứ nhất đượcgọilàtrỏđếnbiếnthứ hai.
  3. 1. Gi ớithii thiệu Biến trong Địa chỉ bộ nhớ bộ nhớ Mộtbiến đượccấp phát ô nhớ tại địachỉ 1000 có giá trị là địa chỉ (1003) của1biến khác. Biếnthứ nhất đượcgọilàcontrỏ. Bộ nhớ
  4. 2. Khai báo biến con trỏ y Cú pháp: type *pointerVariable; type:xác: xác định ki ểudu dữ liệucu củabia biếnmàn mà con trỏ trỏ đến. Ví d ụ: int *a; a
  5. 3. Toán tử con trỏ (pppointer operators) y Toán tử & là toán tử 1 ngôi, trả về địa chỉ bộ nhớ của toán hạng của nó. ◦ Toán tử & dùng để gán địa chỉ của biến cho biến con trỏ Cú pppháp: =&
  6. 3. Toán tử con trỏ (pointer operators) y Ví dụ: a 25 x int a=25, x; int *y; y y x=a; y=&a;
  7. 3. Toán tử con trỏ (pointer operators) y Toán tử * : là toán tử một ngôi trả về giá trị tại địa chỉ con trỏ trỏ đến. Cú pháp: * Ví dụ: a=*pp; ;
  8. 4. Các thao tác trên con tr ỏ y Lệnh gán con trỏ Có thể dùng phép gán để gán giá trị củamột con trỏ cho mộtcontrỏ khác có cùng kiểu Ví dụ: int x; int *p1, *p2; p1 = &x; p2 = p1; Sau khi đọan lệnh trên được thực hiện, cả hai p1 và p2 cùng trỏ đến biến x.
  9. 4. Các thao tác trên con tr ỏ y Phép toán số học trên con trỏ ◦ Chỉ có 2 phép toán sử dụng trên con trỏ là phép cộng và trừ ◦ Khi cộng (+) hoặctrừ (-) 1 con trỏ với1số nggyuyên N; kết quả trả về là 1 con trỏ.Con trỏ này chỉđến vùng nhớ cách vùng nhớ của con trỏ hiệntạimộtsố nguyên lầnkích thướccủa kiểu dữ liệucủanó.
  10. 4. Các thao tác trên con tr ỏ Ví dụ : char *a; short *b; long *c; Các con trỏ a, b, c lần lượt trỏ tới ô nhớ 1000, 2000 và 3000. Cộng các con trỏ với một số nguyên: a = a + 1//1;//con trỏ a dời đii1b 1 byte b = b + 1;//con trỏ b dời đi 2 byte c = c + 1; //con trỏ ccd dời đii4byte 4 byte
  11. 4. Các thao tác trên con tr ỏ
  12. 4. Các thao tác trên con tr ỏ y Lưuý:cả hai toán tử tăng (++) và giảm ( ) đềucóquyền ưutiênlớnhơntoántử * Ví dụ: *p++; Lệnh *p++ tương đương với *(p++) : thực hiện là tăng p (địa chỉ ô nhớ mà nó trỏ tới chứ không phảilàgiátrị trỏ tới).
  13. 4. Các thao tác trên con tr ỏ Ví dụ: *p++ = *q++; y Cả hai toán tử tăng (++) đều được thực hiện sau khi giá trị của *q được gán cho *p và sau đó cả q và p đều tăng lên 1. Lệnh này tương đương với: *p = *q; p++; q++;
  14. 4. Các thao tác trên con tr ỏ #include #include void main () { int a = 20, b = 15, *pa, *pb, temp; pa = &a; // con trỏ pa chứa địa chỉ của a pb = &b; // con tr ỏ pb ch ứa địacha chỉ củaba b temp = *pa; *pa = *pb; // kết quả xuất ra *pb = temp; màhìhàn hình cout << "a = " << a << endl; a = 15 cout << “b = ” << b; b = 20 }
  15. 5. C ấpphátbp phát bộ nhớ động y Con trỏ cung cấpsự hổ trợ cho cấpphátbộ nhớđộng trong C/C++. y Cấpphátđộng là phương tiệnnhờđómột chương trìhình có thể dành đượcthêm bộ nhớ trong khi đang thựcthi,giảiphóngbộ nhớ khi không cần thiết y C/C++ hổ trợ hai hệ thống cấpphátđộng: một hệ thống được định nghĩa bởi C và một được định nghĩabởi C++.
  16. 5. C ấpphátbp phát bộ nhớ động y Cấpphátđộng được định nghĩabởiC −Vùng nhớ Heap đượcsử dụng cho việccấp phát động các khốibộ nhớ trong thờigian thựcthichương trình. Gọilàbộ nhớđộng. −Hàm malloc() và free() dùng để cấp phát và thu hồibộ nhớ,trongthư viện stdlib.h
  17. 5. C ấpphátbp phát bộ nhớ động y Hàm malloc(): cấp phát bộ nhớ động. −Prototype của hàm có d ạng void *malloc(length) − length: là số byte muốn cấp phát. − Hàm malloc() trả về mộtcontrỏ có kiểu void, do đócóthể gán nó cho con trỏ có kiểubấtkỳ. −Sau khi cấp phát thành công, hàm malloc() trả về địa chỉ của byte đầu tiên của vùng nhớđượccấppháttừ heap. Nếu không thành công ((gkhông có đủ vùng nhớ rỗi yêu cầu), hàm malloc() trả về null.
  18. 5. C ấpphátbp phát bộ nhớ động y Ví dụ: char *p; p = (char *) malloc(1000); //cấp phát 1000 bytes Vì hàm malloc() trả về con trỏ kiểu void, nên phảiépkiểu (casting) nó thành con trỏ char cho phù hợpvớibiếncontrỏ p.
  19. 5. C ấpphátbp phát bộ nhớ động y Ví dụ: int *p; p = (int *) malloc(50*sizeof(())int)); Toán tử sizeof để xác định kích thướckiểu dữ liệuint.
  20. 5. C ấpphátbp phát bộ nhớ động y Kích thướccủaheapkhôngxácđịnh nên khi cấpphátbộ nhớ phảikiểmtragiá trị trả về củahàmmalloc()để biếtlàbộ nhớ có được cấp phát thành công hay không. Ví dụ: p = (int *)malloc(100); if(p == NULL) { cout << "Khong du bo nho"; exit(1); }
  21. 5. C ấpphátbp phát bộ nhớ động y Hàm free(): Trả về vùng nhớ được cấp phát bởi hàm malloc(). y Cú pháp: void free(void *p); p là con trỏ đến vùng nhớ đã được cấp phát trước đó bởi hàm malloc().
  22. 5. C ấpphátbp phát bộ nhớ động y Cấp phát động được định nghĩa bởi C++ C++ cung cấphaitoántử cấpphátbộ nhớ động: new và delete. −Toán tử new cấpphátbộ nhớ và trả về mộtcontrỏđếnbyte đầutiêncủavùng nhớ đượccấpphát. −Toán tử delete thu hồivùng nhớđượccấp phát trước đóbởitoántử new.
  23. 5. C ấpphátbp phát bộ nhớ động y Cú pháp: p = new type; delete p; y plàmộtbiếncontrỏ nhận địachỉ của vùng nhớđượccấp phát đủ lớn để chứa1đối tượng có kiểulàtype
  24. 5. C ấpphátbp phát bộ nhớ động y Ví dụ: #include #include int main() { int *p; p = new it//llint; // allocat e space for an itint *p = 100; cout << "At " << p << "" ; cout << "is the value " << *p << "\n"; delete p; ret0turn 0; }
  25. 6. Con tr ỏ void (void pointers ) y Con trỏ void là mộtlọai con trỏđặcbiệtmà có thể trỏđếnbấtkỳ kiểudữ liệunào. y Cú pháp: void *pointerVariable; y Ví dụ: void *p; p = &a; // p trỏ đến biến nguyên a p = &f; //p trỏ đến biến thực f
  26. 6. Con tr ỏ void (void pointers ) y Kiểudữ liệu khi khai báo biếncontrỏ chính là kiểudữ liệucủaônhớ mà con trỏ có thể trỏ đến. y Địachỉ đặtvào biếncontrỏ phảicùng kiểuvới kiểucủacontrỏ Ví dụ: int a; float f; int *fl*f*pa; float *pf; pa = &a; pf = &f;// hợp lệ pa = &f; pf = &a; //không hợplệ
  27. 6. Con tr ỏ void (void pointers ) y Tuy nhiên, ta cũng có thể ép kiểucontrỏ về đúng kiểutương ứng khi dùng trong các biểu thức. Vídí dụ: ◦ Nếu p đang trỏ đến biến nguyên a, để tăng giáiá t rị của biến a lên 10 t a p hảidùi dùng l ệnh sau: (int*)*p + 10; ◦ Nếu p đang trỏ đến biến thực f, để tăng giá trị củabia biếnflên10taphn f lên 10 ta phảidi dủng l ệnh sau: (float*)*p + 10;
  28. 7. Con tr ỏ null ( Null pointers ) y Mộtcontrỏ hiệnhànhkhôngtrỏđếnmột địa chỉ bộ nhớ hợplệ thì được gán giá trị NULL y NULL được định nghĩa trong Ví dụ: #include void main() {int *p; cout <<“Gia tri con tro p tro den la: “<< *p; } x Kết quả của chương trình trên là: NULL POINTER ASSIGNMENT
  29. 8. Con tr ỏ và m ảng y Giữamảng và con trỏ có mộtsự liên hệ rất chặtchẽ: ◦ Những phầntử củamảng đượcxácđịnh bằng chỉ số trong mảng và cũng có thể được xác định qua biếncontrỏ. ◦ Tên củamộtmảng tương đương với địachỉ phầntửđầutiêncủanó,tương tự mộtcon trỏ tương đương với địachỉ củaphần tử đầu tiên mà nó trỏ tới.
  30. 8. Con tr ỏ và m ảng Ví dụ: char ch[10], *p; p = ch;
  31. 8. Con tr ỏ và m ảng y p đượcgánđịachỉ củaphầntửđầutiêncủa mảng ch. p = ch; y Để tham chiếuphầntử thứ 3trongmảng ch, ta dùng một trong 2 cách sau: x ch[2] x *(p+2).
  32. 8. Con tr ỏ và m ảng y Truy cập các phần tử mảng bằng con trỏ Kiểumảng Kiểu con trỏ & [0] &Tê& [[V ] + [ ] *( + )
  33. 8. Con tr ỏ và m ảng Ví dụ: #include #include void main () { int numbers[5], * p; p = numbers; *p = 10; p++; *p = 20; p = &numbers[2]; *p = 30; p = numbers + 3; *p = 40; p = numbers; *(p+4) = 50; for (int n=0; n<5; n++) cout << numbers[n] << ", "; }
  34. 8. Con tr ỏ và m ảng int Numbers[5]; Numbers 10 20 3040 50 int *p; p pp p p p= Numbers; p 20 *p = 10; p++; *p = 20; p = &numbers[2]; *p = 30; p = numbers + 3; *p = 40; p = numbers; *(p+4) = 50;
  35. 8. Con tr ỏ và m ảng Ví dụ: Xuất mảng sử dụng con trỏ #include void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; int *p; p = a; for(int i=0 ; i<10 ; i++) { *(p+i) *= 10; //tuong duong a[i] = a[i]*10 cout << “a[“ << i << “] = “ << *(p+i) << ”\n”; } }
  36. 9. M ảng con trỏ y Mỗibiếncontrỏ là mộtbiến đơn. Ta có thể tạomảng củacáccontrỏ vớimỗiphầntử của mảng là mộtcontrỏ. y Cúháú pháp: type *pointerArray[elements]; − type:kiểudữ liệumàcáccontrỏ phầntử trỏđến. − poitinterA rray: tênmảng con trỏ. − elements:số phầntử củamảng con trỏ.
  37. 9. M ảng con trỏ Ví dụ: P[0] P[1] P[2] P[3] P[4] int *p[5]; p 100 int a=6; p[0] = &a; a 66 100 p[2] = p[0]; int b; b b = *p[0];