[Training_C++] Con Trỏ - Pointer - Programming Tutorial
Có thể bạn quan tâm
Programming Tutorial Được tạo bởi Blogger.
9/09/2014 10:33:00 SA 1. Giới thiệu về biến con trỏ: - Biến con trỏ không chứa dữ liệu mà chỉ chứa địa chỉ của dữ liệu hay chứa địa chỉ của ô nhớ dữ liệu. - Kích thước của biến con trỏ không phụ thuộc vào kiểu dữ liệu, luôn luôn bằng 4byte (đối với hệ thống window 32 bit). 2. Khai báo biến con trỏ: Khai báo biến con trỏ: Cú pháp: <Kiểu dữ liệu> * <tên con trỏ>; Ý nghĩa: Khai báo một biến có tên con trỏ dùng để chứa địa chỉ của các biến có kiểu <Kiểu>. Ví dụ: int a = 10;// (1) int *p; // (2) p = &a; // (3) Biểu diễn biến a và biến con trỏ p trong bộ nhớ:
Chương trình sẽ thực thi như sau: (1): Cấp phát cho biến tĩnh a một vùng nhớ (trên stack) và gán giá trị ô nhớ bằng 10. (2): Cấp phát cho biến con trỏ p một vùng nhớ (trên stack). (3): Gán giá trị ô nhớ của biến con trỏ p bằng địa chỉ của biến a. Ghi chú: Nếu chưa muốn khai báo kiểu dữ liệu mà con trỏ ptr trỏ đến, ta sử dụng: void * ptr;//con trỏ ptr có thể trỏ đến bất kỳ vùng nhớ có kiểu dữ liệu gì. 3. Thao tác với biến con trỏ: - Toán tử & khi đặt trước một biến nào đó tức là lấy địa chỉ của biến đó. Ví dụ: . &a sẽ có giá trị 0x12345678 (xem hình trên) . &p sẽ có giá trị 0x87654321 (xem hình trên) - Để truy cập đến nội dung của ô nhớ mà con trỏ chỉ tới ta thêm dấu * vào trước biến con trỏ: * <tên con trỏ> Ví dụ: . *p sẽ có giá trị bằng 10, tức là nội dung của ô nhớ mà con trỏ p trỏ tới (xem hình trên) - Còn p là nội dung ô nhớ của con trỏ p bằng 0x12345678 (địa chỉ của biến a). 4. Cấp phát và giải phóng vùng nhớ cho biến con trỏ quản lý: Cấp phát vùng nhớ động: Có 2 vùng nhớ: - Vùng nhớ stack là vùng nhớ tĩnh, vùng nhớ có giới hạn được cấp phát để lưu các biến: local variable, tham số truyền vào một phương thức, hoặc các biến khai báo bên trong một biên thức, biến tham chiếu và gọi hàm. - Vùng nhớ heap gọi là vùng nhớ động. Các vùng nhớ khi cấp phát trên vùng nhớ heap có thể giải phóng để thu hồi vùng nhớ khi không sử dụng. Các vùng nhớ được cấp phát động thông qua các hàm như: . void* maloc(size_t size); . void* calloc (size_t num, size_t size); . Toán tử New - Ví dụ: cấp phát vùng nhớ động int *p = new int[n]; // (1)
Vùng nhớ của biến con trỏ p được lưu trữ trên vùng nhớ stack, còn vùng nhớ mà con trỏ p trỏ đến nằm ở vùng nhớ heap. Giải phóng vùng nhớ con trỏ p trỏ đến:
- Có 2 bước: 1. Xóa vùng nhớ mà con trỏ p trỏ đến: delete[]p;//thêm dấu [] nếu p trỏ đến mảng vùng nhớ int *p = new int[n];//n ô nhớ deletep; // nếu p trỏ đến 1 ô vùng nhớ int *p = new int; 2. Sau khi xóa vùng nhớ p trỏ đến để thì gán nội dung con trỏ p = 0;//hoặc NULL để tránh p trỏ tới vùng nhớ không còn tồn tại 5. Các phép toán trên con trỏ: Phép gán con trỏ: hai con trỏ cùng kiểu có thể gán cho nhau Ví dụ: int a = 10, *p, *q ; float *f; p = &a ; q = p ; // đúng f = p ; // sai do khác kiểu Ta có thể ép kiểu con trỏ theo cú pháp: (<kiểu kết quả> *) <tên con trỏ>; Ví dụ: tiếp theo ví dụ trên f = (float*)p ; // đúng Cộng, trừ con trỏ với một số nguyên: <Kiểu dữ liệu x> * p = new <Kiểu dữ liệu x>[n];//Tạo mảng vùng nhớ Có thể cộng trừ con trỏ với một số nguyên n nào đó (p + n) và kết quả trả về là một con trỏ, con trỏ này trỏ đến vùng nhớ cách vùng nhớ của con trỏ hiện tại n * sizeof(kiểu dữ liệu x của con trỏ). Lưu ý: - Con trỏ có giá trị bằng NULL là con trỏ không trỏ đến địa chỉ nào cả. - Không thể cộng hai con trỏ với nhau. - Phép trừ hai con trỏ cùng kiểu sẽ trả về 1 giá trị chính là khoản cách (số phần tử) giữa 2 con trỏ đó. 6. Con trỏ và mảng: Mảng một chiều: Con trỏ và mảng: <kiểu dữ liệu x> a[n] = {a1, a2, ..., an};//alàmộtmảngnphầntửcókiểudữliệux. <kiểu dữ liệu x> *p; p = a; Lúc này: *(p + i) chính bằng a[i] Với khai báo như trên thì ta có một số tính toán như sau: (1) Đối với mảng a: 1. *a : = a[0] (vì a là địa chỉ của mảng a nên khi * sẽ lấy nội dung) 2. &a :chođịachỉa (cũng bằng a) 3. &a + 1 :sẽcộngthêmsốbytebằngkíchcỡvùngnhớ của mảng a, cộng thêm n *sizeof(x) 4. a + 1 : alàđịachỉcủaa,cộngthêmsizeof(x) 5. a++ :lỗi (câu lệnh này tương đương a = a + 1 do a một hằng nên không thể gán lại giá trị khác) (2) plàmộtcontrỏkiểuxtrỏvàomảnga. (tứclàp = a;) 1. *p :giátrịônhớptrỏtới 2. &p :địachỉcủap 3. &p+1:sẽcộngthêmsốbytebằngkíchcỡcủacontrỏp,tức= 4 byte (windows 32 bits) 4. p+1 :nộidungcủacontrỏp +cộngthêmsizeof(kiểuxcủacontrỏp) 5. p++ : lênh này tương đương gán lại p = p + 1 nên kết quả như trên, cộngthêmsizeof( kiểuxcủacontrỏp) Ví dụ về con trỏ vs với mảng: char a[6] = {10, 20, 30, 40, 50, 60}; char *p = a;
Tính các kết quả sau: a = ? p = ? &a = ?&p = ? *a = ? *p = ? &a + 1 = ? &p + 1 = ?; p + 1 = ? (*p) + 1 = ? *(p + 1) = ? a++; a = ? p++; p = ? Đáp án: a = ? p = ? &a = ?&p = ? *a = ? *p = ? &a + 1 = ? &p + 1 = ?; p + 1 = ? (*p) + 1 = ? *(p + 1) = ? a++; a = ? p++; p = ? 7. Con trỏ hàm: (1) Ta có một hàm như sau: <KiểuDữLiệuHàm> Tên_Hàm_A(<kiểuthamsố_1> [*][&]ThamSo_1,.., <kiểuthamsố_n> [*][&]ThamSo_n){ //code here ... } (2) Khai báo một con trỏ hàm trỏ đến hàm trên, cú pháp như sau: <KiểuDữLiệuHàm> (*Tên_ConTrỏ_Hàm)(<kiểuthamsố_1> [*][&],..,<kiểuthamsố_n> [*][&]) (3) Gán giá trị (địa chỉ ) cho con trỏ hàm: Tên_ConTrỏ_Hàm = Tên_Hàm_A;//hoặc &Tên_Hàm_A (4) Cách gọi hàm: Tên_ConTrỏ_Hàm(ThamSo_1, …,ThamSo_n); Ví dụ về con trỏ hàm: #include <iostream> void Foo(int &n) { n++; } void main() { int x = 10; void (*ptrFoo)(int &);//Khai báo con trỏ hàm ptrFoo = Foo; //Gán địa chỉ cho con trỏ hàm ptrFoo(x); //Gọi con trỏ hàm printf("x = %d\n", x); getchar(); } Ví dụ về con trỏ hàm: đối số truyền vào là con trỏ hàm #include <stdio.h> int Add(int a, int b) { return a + b; } int Sub(int a, int b) { return a - b; } //pFunction là tham số con trỏ hàm cho một hàm khác int Calc(int a, int b, int (*pFunction)(int, int)) { return (pFunction)(a, b); } void main() { int a = 11, b = 10; printf("Result = %d\n", Calc(a, b, Add));//Truyền con trỏ hàm printf("Result = %d\n", Calc(a, b, Sub));//Truyền con trỏ hàm getchar(); } 8. Bài tập về con trỏ: Bài 1: Bài 2: Bài 3: Bài 4: Bài 5:
Chuyên mục C Bài đăng Mới hơn Bài đăng Cũ hơn Trang chủ
HTML/CSS
tiện ích HTML cssTổng số lượt xem trang:
Danh sách các chuyên mục
- Android (38)
- C (15)
- Java_Basic (23)
- Test (1)
- Utity (2)
Các chuyên mục chính
Android Java_BasicTìm kiếm nội dung bài viết:
[Training_C++] Con trỏ - Pointer
9/09/2014 10:33:00 SA 1. Giới thiệu về biến con trỏ: - Biến con trỏ không chứa dữ liệu mà chỉ chứa địa chỉ của dữ liệu hay chứa địa chỉ của ô nhớ dữ liệu. - Kích thước của biến con trỏ không phụ thuộc vào kiểu dữ liệu, luôn luôn bằng 4byte (đối với hệ thống window 32 bit). 2. Khai báo biến con trỏ: Khai báo biến con trỏ: Cú pháp: <Kiểu dữ liệu> * <tên con trỏ>; Ý nghĩa: Khai báo một biến có tên con trỏ dùng để chứa địa chỉ của các biến có kiểu <Kiểu>. Ví dụ: int a = 10;// (1) int *p; // (2) p = &a; // (3) Biểu diễn biến a và biến con trỏ p trong bộ nhớ:
Chương trình sẽ thực thi như sau: (1): Cấp phát cho biến tĩnh a một vùng nhớ (trên stack) và gán giá trị ô nhớ bằng 10. (2): Cấp phát cho biến con trỏ p một vùng nhớ (trên stack). (3): Gán giá trị ô nhớ của biến con trỏ p bằng địa chỉ của biến a. Ghi chú: Nếu chưa muốn khai báo kiểu dữ liệu mà con trỏ ptr trỏ đến, ta sử dụng: void * ptr;//con trỏ ptr có thể trỏ đến bất kỳ vùng nhớ có kiểu dữ liệu gì. 3. Thao tác với biến con trỏ: - Toán tử & khi đặt trước một biến nào đó tức là lấy địa chỉ của biến đó. Ví dụ: . &a sẽ có giá trị 0x12345678 (xem hình trên) . &p sẽ có giá trị 0x87654321 (xem hình trên) - Để truy cập đến nội dung của ô nhớ mà con trỏ chỉ tới ta thêm dấu * vào trước biến con trỏ: * <tên con trỏ> Ví dụ: . *p sẽ có giá trị bằng 10, tức là nội dung của ô nhớ mà con trỏ p trỏ tới (xem hình trên) - Còn p là nội dung ô nhớ của con trỏ p bằng 0x12345678 (địa chỉ của biến a). 4. Cấp phát và giải phóng vùng nhớ cho biến con trỏ quản lý: Cấp phát vùng nhớ động: Có 2 vùng nhớ: - Vùng nhớ stack là vùng nhớ tĩnh, vùng nhớ có giới hạn được cấp phát để lưu các biến: local variable, tham số truyền vào một phương thức, hoặc các biến khai báo bên trong một biên thức, biến tham chiếu và gọi hàm. - Vùng nhớ heap gọi là vùng nhớ động. Các vùng nhớ khi cấp phát trên vùng nhớ heap có thể giải phóng để thu hồi vùng nhớ khi không sử dụng. Các vùng nhớ được cấp phát động thông qua các hàm như: . void* maloc(size_t size); . void* calloc (size_t num, size_t size); . Toán tử New - Ví dụ: cấp phát vùng nhớ động int *p = new int[n]; // (1)
Vùng nhớ của biến con trỏ p được lưu trữ trên vùng nhớ stack, còn vùng nhớ mà con trỏ p trỏ đến nằm ở vùng nhớ heap. Giải phóng vùng nhớ con trỏ p trỏ đến:
- Có 2 bước: 1. Xóa vùng nhớ mà con trỏ p trỏ đến: delete[]p;//thêm dấu [] nếu p trỏ đến mảng vùng nhớ int *p = new int[n];//n ô nhớ deletep; // nếu p trỏ đến 1 ô vùng nhớ int *p = new int; 2. Sau khi xóa vùng nhớ p trỏ đến để thì gán nội dung con trỏ p = 0;//hoặc NULL để tránh p trỏ tới vùng nhớ không còn tồn tại 5. Các phép toán trên con trỏ: Phép gán con trỏ: hai con trỏ cùng kiểu có thể gán cho nhau Ví dụ: int a = 10, *p, *q ; float *f; p = &a ; q = p ; // đúng f = p ; // sai do khác kiểu Ta có thể ép kiểu con trỏ theo cú pháp: (<kiểu kết quả> *) <tên con trỏ>; Ví dụ: tiếp theo ví dụ trên f = (float*)p ; // đúng Cộng, trừ con trỏ với một số nguyên: <Kiểu dữ liệu x> * p = new <Kiểu dữ liệu x>[n];//Tạo mảng vùng nhớ Có thể cộng trừ con trỏ với một số nguyên n nào đó (p + n) và kết quả trả về là một con trỏ, con trỏ này trỏ đến vùng nhớ cách vùng nhớ của con trỏ hiện tại n * sizeof(kiểu dữ liệu x của con trỏ). Lưu ý: - Con trỏ có giá trị bằng NULL là con trỏ không trỏ đến địa chỉ nào cả. - Không thể cộng hai con trỏ với nhau. - Phép trừ hai con trỏ cùng kiểu sẽ trả về 1 giá trị chính là khoản cách (số phần tử) giữa 2 con trỏ đó. 6. Con trỏ và mảng: Mảng một chiều: Con trỏ và mảng: <kiểu dữ liệu x> a[n] = {a1, a2, ..., an};//alàmộtmảngnphầntửcókiểudữliệux. <kiểu dữ liệu x> *p; p = a; Lúc này: *(p + i) chính bằng a[i] Với khai báo như trên thì ta có một số tính toán như sau: (1) Đối với mảng a: 1. *a : = a[0] (vì a là địa chỉ của mảng a nên khi * sẽ lấy nội dung) 2. &a :chođịachỉa (cũng bằng a) 3. &a + 1 :sẽcộngthêmsốbytebằngkíchcỡvùngnhớ của mảng a, cộng thêm n *sizeof(x) 4. a + 1 : alàđịachỉcủaa,cộngthêmsizeof(x) 5. a++ :lỗi (câu lệnh này tương đương a = a + 1 do a một hằng nên không thể gán lại giá trị khác) (2) plàmộtcontrỏkiểuxtrỏvàomảnga. (tứclàp = a;) 1. *p :giátrịônhớptrỏtới 2. &p :địachỉcủap 3. &p+1:sẽcộngthêmsốbytebằngkíchcỡcủacontrỏp,tức= 4 byte (windows 32 bits) 4. p+1 :nộidungcủacontrỏp +cộngthêmsizeof(kiểuxcủacontrỏp) 5. p++ : lênh này tương đương gán lại p = p + 1 nên kết quả như trên, cộngthêmsizeof( kiểuxcủacontrỏp) Ví dụ về con trỏ vs với mảng: char a[6] = {10, 20, 30, 40, 50, 60}; char *p = a;
Chuyên mục C Bài đăng Mới hơn Bài đăng Cũ hơn Trang chủ Danh mục bài viết
- Android (38)
- C (15)
- Java_Basic (23)
Các bài phổ biến
- [C++] Hướng dẫn tạo và sử dụng thư viện LIB và DLL
- Các cách thiết kế button trong android đẹp
- Bài 11: Xử lý JSON trong Android
- Bit Endian và Little Endian trong lập trình
Bài viết theo ngày tháng
- ► 2016 (3)
- ► tháng 5 (1)
- ► tháng 4 (1)
- ► tháng 3 (1)
- ► 2015 (63)
- ► tháng 12 (1)
- ► tháng 10 (1)
- ► tháng 8 (32)
- ► tháng 7 (25)
- ► tháng 4 (2)
- ► tháng 1 (2)
Từ khóa » ép Kiểu Con Trỏ Trong C
-
Hỏi Về ép Kiểu Trong Con Trỏ Trong C/C++ - Dạy Nhau Học
-
Con Trỏ (pointer) Từ Cơ Bản Tới Nâng Cao Phần 2 - CoderDocs
-
Ép Kiểu Trong C++ - Techacademy
-
Lập Trình C: Con Trỏ (Pointer) | V1Study
-
Ép Kiểu Trong C - Hoclaptrinh
-
Mỗi Ngày Một Kiến Thức Mới - Tìm Hiểu Về Con Trỏ Trong C++ Con Trỏ ...
-
Ép Kiểu Trong C - VietTuts
-
Con Trỏ Void* - Viblo
-
Bài 11: Con Trỏ Trong C - Học Lập Trình C Cơ Bản
-
Lập Trình C - Con Trỏ Void
-
Vì Sao Cách ép Kiểu Trong C Không An Toàn Và Nên Sử Dụng ...
-
Con Trỏ Void (Void Pointers) | How Kteam
-
Con Trỏ Trong C++ - Pointer — Modern C++ - STDIO