Con trỏ và mảng C
Con trỏ & Mảng
Bạn cũng có thể sử dụng con trỏ để truy cập mảng .
Xét mảng số nguyên sau:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
Bạn đã học được từ chương về mảng rằng bạn có thể lặp qua các phần tử của mảng bằng vòng lặp for
:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
int i;
for (i = 0; i < 4;
i++) {
printf("%d\n", myNumbers[i]);
}
Kết quả:
25
50
75
100
Thay vì in giá trị của từng phần tử mảng, hãy in địa chỉ bộ nhớ của từng phần tử mảng:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
int i;
for (i = 0; i < 4;
i++) {
printf("%p\n", &myNumbers[i]);
}
Kết quả:
0x7ffe70f9d8f0
0x7ffe70f9d8f4
0x7ffe70f9d8f8
0x7ffe70f9d8fc
Lưu ý rằng số cuối cùng trong địa chỉ bộ nhớ của mỗi phần tử là khác nhau, cộng thêm 4.
Đó là vì kích thước của kiểu int
thường là 4 byte, hãy nhớ:
Ví dụ
// Create an int variable
int myInt;
// Get the memory size of an int
printf("%lu", sizeof(myInt));
Kết quả:
4
Vì vậy, từ "ví dụ về địa chỉ bộ nhớ" ở trên, bạn có thể thấy rằng trình biên dịch dự trữ 4 byte bộ nhớ cho mỗi phần tử mảng, có nghĩa là toàn bộ mảng chiếm 16 byte (4 * 4) bộ nhớ lưu trữ:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
// Get the size of the myNumbers
array
printf("%lu", sizeof(myNumbers));
Kết quả:
16
Con trỏ liên quan đến mảng như thế nào
Được rồi, vậy mối quan hệ giữa con trỏ và mảng là gì? Vâng, trong C, tên của một mảng thực sự là một con trỏ tới phần tử đầu tiên của mảng.
Bối rối? Hãy cố gắng hiểu điều này rõ hơn và sử dụng lại "ví dụ về địa chỉ bộ nhớ" của chúng tôi ở trên.
Địa chỉ bộ nhớ của phần tử đầu tiên giống với tên của mảng :
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
// Get the memory address of the
myNumbers array
printf("%p\n", myNumbers);
// Get the memory
address of the first array element
printf("%p\n", &myNumbers[0]);
Kết quả:
0x7ffe70f9d8f0
0x7ffe70f9d8f0
Về cơ bản, điều này có nghĩa là chúng ta có thể làm việc với mảng thông qua con trỏ!
Làm sao? Vì myNumbers là một con trỏ tới phần tử đầu tiên trong myNumbers nên bạn có thể sử dụng toán tử *
để truy cập nó:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
// Get the value of the first
element in myNumbers
printf("%d", *myNumbers);
Kết quả:
25
Để truy cập phần tử còn lại trong myNumbers, bạn có thể tăng con trỏ/mảng (+1, +2, v.v.):
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
// Get the value of the second
element in myNumbers
printf("%d\n", *(myNumbers + 1));
// Get the value of the
third
element in myNumbers
printf("%d", *(myNumbers + 2));
//
and so on..
Kết quả:
50
75
Hoặc lặp qua nó:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
int *ptr = myNumbers;
int i;
for (i = 0; i < 4; i++) {
printf("%d\n", *(ptr + i));
}
Kết quả:
25
50
75
100
Cũng có thể thay đổi giá trị của các phần tử mảng bằng con trỏ:
Ví dụ
int myNumbers[4] = {25, 50, 75, 100};
// Change the
value of the first element to 13
*myNumbers = 13;
// Change the
value of the second element to 17
*(myNumbers +1) = 17;
// Get
the value of the first element
printf("%d\n", *myNumbers);
// Get
the value of the second element
printf("%d\n", *(myNumbers + 1));
Kết quả:
13
17
Cách làm việc với mảng này có vẻ hơi quá đáng. Đặc biệt với các mảng đơn giản như trong ví dụ trên. Tuy nhiên, đối với các mảng lớn, việc truy cập và thao tác các mảng bằng con trỏ có thể hiệu quả hơn nhiều.
Nó cũng được coi là nhanh hơn và dễ dàng hơn để truy cập mảng hai chiều bằng con trỏ.
Và vì chuỗi thực chất là mảng nên bạn cũng có thể sử dụng con trỏ để truy cập chuỗi .
Hiện tại, thật tuyệt khi bạn biết cách hoạt động của nó. Nhưng giống như chúng tôi đã chỉ ra ở chương trước; con trỏ phải được xử lý cẩn thận vì có thể ghi đè lên dữ liệu khác được lưu trong bộ nhớ.