Menu-ngang

☰ MENU

20/03/2022

Chương 6: Con trỏ

 

6.1. Khái niệm về con trỏ và địa chỉ

- Con trỏ (Pointer) là một kiểu dữ liệu đặc biệt dùng đê quản lý địa chỉ của các ô nhớ. Một con trỏ quản lý các địa chỉ mà dữ liệu tại các địa chỉ này có kiểu T thì con trỏ đó được gọi là con trỏ kiểu T.

- Con trỏ kiểu T chỉ được dùng để chứa địa chỉ của biến kiểu T. Nghĩa là con trỏ kiểu int chỉ được dùng để chứa biến kiểu int, con trỏ kiểu char chỉ được dùng chứa biến kiểu char.

 6.2. Khai báo biến con trỏ

Cú pháp <tên kiểu dữ liệu> *<tên biến con trỏ>

Ví dụ 6.1:

// x là biến kiểu int, còn px là con trỏ kiểu int.

int x, *px;

px được khai báo là một con trỏ kiểu int, nó chứa địa chỉ của biến kiểu dữ liệu số nguyên.

- Dấu * không phải là một phần của biến, int * có nghĩa là con trỏ kiểu int.

- Đặt tên biến con trỏ giống như tên của các biến khác.

 

6.3. Các thao tác trên con trỏ

6.3.1. Gán địa chỉ của biến cho con trỏ

Toán tử địa chỉ (&)

- Biến được khai báo là a thì &a là địa chỉ của a.

- Kết quả của phép lấy địa chỉ (&) là một con trỏ, do đó có thể dùng để gán cho một biến pointer.

Ví dụ 6.2: Để gán địa chỉ vào con trỏ chúng ta cần phải gán giá trị cho biến như sau:

int a = 10;

int *p;

p = &a;// giá trị p chứa địa chỉ của biến a



6.3.2. Nội dung của ô nhớ con trỏ chỉ tới

Toán tử nội dung (*)

Toán tử lấy nội dung của một địa chỉ được kí hiệu là dấu * trước một pointer, dùng để lấy giá trị của biến mà con trỏ đang trỏ đến.

Ví dụ 6.3:

int *p, a = 10 ;

p= &a ;

int k = *p + 3 ;

//giá trị của *p (tức là a) cộng thêm 3, gán cho k. Sau câu lệnh trên k = 13

 6.3.3. Cấp phát và giải phóng vùng nhớ

a. Cấp phát vùng nhớ cho biến con trỏ

Trước khi sử dụng biến con trỏ, ta nên cấp phát vùng nhớ cho biến con trỏ này quản lý địa chỉ. Việc cấp phát được thực hiện nhờ các hàm malloc(), trong

thư viện alloc.h.

Cú pháp:

void *malloc(size_t size): Cấp phát vùng nhớ có kích thước size.

void *calloc(size_t nitems, size_t size): Cấp phát vùng nhớ có kích thước là nitems*size.

Ví dụ 6.4: Giả sử ta có khai báo:

int a, *pa, *pb;

pa = (int*)malloc(sizeof(int)); /* Cấp phát vùng nhớ

có kích thước bằng với kích thước của một số

nguyên */

pb= (int*)calloc(10, sizeof(int)); /* Cấp phát vùng

nhớ có thể chứa được 10 số nguyên*/

Hình ảnh minh họa trong bộ nhớ như sau:



Lưu ý: Khi sử dụng hàm malloc() hay calloc(), ta phải ép kiểu vì nguyên mẫu các hàm này trả về con trỏ kiểu void.

b. Cấp phát lại vùng nhớ cho biến con trỏ

Trong quá trình thao tác trên biến con trỏ, nếu ta cần cấp phát thêm vùng nhớ có kích thước lớn hơn vùng nhớ đã cấp phát, ta sử dụng hàm realloc().

Cú pháp: void *realloc(void *block, size_t size)

Ví dụ 6.5: Trong ví dụ trên ta có thể cấp phát lại vùng nhớ do con trỏ pa quảnlý như sau:

int a, *pa;

/*Cấp phát vùng nhớ có kích thước 2 byte*/

pa=(int*)malloc(sizeof(int));

/* Cấp phát lại vùng nhớ có kích thước 6 byte*/

pa = realloc(pa, 6);

c. Giải phóng vùng nhớ cho biến con trỏ

Một vùng nhớ đã cấp phát cho biến con trỏ, khi không còn sử dụng nữa, ta sẽ thu hồi lại vùng nhớ này nhờ hàm free().

Cú pháp: void free(void *block)

Ví dụ 6.7: Xét lại ví dụ 6.4, sau khi thực hiện xong, ta giải phóng vùng nhớ cho 2 biến con trỏ pa & pb:

free(pa);

free(pb);

 6.3.4. Một số phép toán

Một biến pointer có thể được cộng trừ với một số nguyên (int, long) để cho kết quả là một pointer chỉ đến một vùng nhớ khác.

Ví dụ 6.8:

int *ptr, *p1;

int num = 10;

ptr = &num;

p1 = ptr + 2;

Việc cộng hoặc trừ pointer với một số nguyên n thì pointer sẽ chỉ đến một địa chỉ mới hay nói cách khác là chỉ đến một biến khác nằm cách biến đó n vị trí.

 v    Thc hành:

Sử dụng Con trỏ để viết các chương trình sau:

Bài 1. Viết chương trình nhập vào mảng a gồm n phần tử nhập từ bàn phím. Sau đó xuất ra màn hình mảng vừa nhập.

Bài 2. Viết chương trình sắp xếp một mảng n phần tử theo thứ tự tăng dần.

Bài 3. Viết chương trình nhập vào một mảng, hãy xuất ra màn hình:

- Phần tử lớn nhất của mảng.

- Phần tử nhỏ nhất của mảng.

- Tính tổng của các phần tử trong mảng .