V.4.3 - Liên hệ giữa con trỏ và mảng
Trong C con trỏ và mảng có liên hệ rất chặt chẽ với nhau, như trên chúng ta biết tên mảng là một hằng con trỏ. Hơn nữa các phần tử của mảng có thể được truy xuất thông qua chỉ số hoặc thông qua con trỏ.
Như trên chúng ta biết, mảng được cấp phát tại vùng nhớ nào đó và địa chỉ của vùng nhớ đó chính là địa chỉ của mảng. Tên mảng là con trỏ trỏ tới chính địa chỉ của nó hay nói khác tên mảng là con trỏ lưu địa chỉ của mảng, nhưng là hằng con trỏ. Chúng ta giải thích cụ thể hơn qua ví dụ sau:
Ví dụ với khai báo
int A[3], D[2][5];
thì A, D là các con trỏ và:
A chính là địa chỉ của mảng A, hay bằng &A[0];
tương tự cho mảng D ta cũng có D ⇔ &D[0].
Và theo như cách gọi của con trỏ thì ta nói A là con trỏ trỏ tới phần tử đầu tiên của mảng. Với mảng hai chiều D thì cũng tương tự, D cũng là một con trỏ trỏ tới D[0], và D[0] lại là một con trỏ trỏ tới D[0][0], có thể nói D là con trỏ trỏ tới con trỏ. Như vậy A là mảng kiểu int tức là các phần tử của nó có kiểu int, và như vậy A là con trỏ kiểu int, hay A có kiểu là int *.
T ương tự, D[i] (nó chung là các hàng của mảng D) là con trỏ kiểu int, tức là D[i] có kiểu là int *, và D là con trỏ trỏ tới D[0] - Các D[i] là mảng int[5], vậy D là con trỏ kiểu int [5]. Tên mảng có thể gán cho các (biến) con trỏ có kiểu phù hợp.
Ví dụ:
với các con trỏ và mảng sau
int A[10];
int D[2][4];
int *p;
int 0[4]; // khai báo q là con trỏ kiểu int [4],
chúng ta có thể thực hiện các phép gán sau:
p = A; q = D; p = D[i];
- Truy xuất các phần tử mảng qua con trỏ
Giả sử A là mảng một chiều như trên chúng ta có:
- A là con trỏ trỏ tới A[0] hay A tương đương với &A[0]
- 1 là con trỏ trỏ tới phần tử kiểu T kế tiếp sau A[0] tức là A+1 trỏ tới A[1] hay 1 ⇔ &A[1]
- Tổng quát 0 ⇔ &A[i] Như chúng ta biết từ trước là nếu p là con trỏ lưu địa chỉ của biến x thì * p là giá trị của x.
Như vậy *A chính là giá trị của A[0], *1 là A[1],... tổng quát chúng ta có *0 ⇔A[i]
Ví dụ chúng ta có thể minh họa bằng đoạn lệnh nhập và in các phần tử mảng A như sau:
int A[10];
int i; ....
// nhập mảng A có 10 phần tử
for0 {
printf“A[;
scanf0;
}
// in mảng A có 10 phần tử,
for0 {
printf“A[;
scanf0);
}
Với mảng 2 chiều D[n][m] cũng tương tự như trên ta có:
• D là con trỏ trỏ tới hàng dầu tiên trong mảng tức là:
D ⇔ &D[0] - D[0]
là con trỏ trỏ tới phần tử đầu tiên là
D[0][0] hay D[0] ⇔ &D[0][0] nên *D[0] ⇔ D[0][0];
hay ** D ⇔ D[0][0] - 0 con trỏ tới phần tử D[0][j],
hay 0 ⇔ &D[0][j]
nên ta có *0 ⇔ D[0][j]
hay *0 ⇔ D[0][j]
• Tương tự tổng quát ta có
0 ⇔ &D[i].
- D[i] là con trỏ trỏ tới phần tử đầu tiên là D[i][0]
hay D[i] ⇔ &D[i][0]
nên *D[i] ⇔ D[i][0];
hay *0 ⇔ D[i][0] - 0 con trỏ tới phần tử D[i][j], hay 0 ⇔ &D[i][j]
nên ta có *0 ⇔ D[i][j]
hay tổng quát ta có *0+j) ⇔ D[i][j]