"dereferencing" một con trỏ có nghĩa là truy cập vào các giá trị điểm con trỏ đến. Giả sử các tờ khai sau:
int a = 10;
int *p = &a;
Đây là bản đồ bộ nhớ giả của hai biến:
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
a 0x80001000 0x00 0x00 0x00 0x0A
p 0x80001004 0x80 0x00 0x10 0x00
a
chứa giá trị số nguyên 10 p
chứa địa chỉ của a
(0x80001000). Nếu chúng tôi muốn truy cập nội dung của a
thông qua p
, chúng tôi dereferencep
với nhà điều hành gián tiếp *
. Do đó, biểu thức *p
tương đương với biểu thức a
. Nếu chúng tôi đã viết
*p = 16;
đó là giống như viết
a = 16;
Dưới đây là một đoạn mã ngắn cho thấy làm thế nào để sử dụng một đối tượng kiểu char **
để tạo ra một mảng các chuỗi:
#include <stdlib.h>
#define N 20 // For this example, we will allocate 20 strings
#define LENGTH 10 // of 10 characters each (not counting 0 terminator)
...
char **arr = malloc(sizeof *arr * N);
if (arr)
{
size_t i;
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1));
strcpy(arr[i], " ");
}
}
Đi qua từng dòng một,
char **arr = malloc(sizeof *arr * N);
phân bổ một khối phần tử N, mỗi phần tử đủ lớn để lưu trữ con trỏ đến char (sizeof *arr
== sizeof (char *)
từ loại *arr
== char *
) và gán giá trị con trỏ kết quả thành arr
. IOW, arr
trỏ đến con trỏ đầu tiên đến char
, do đó loại char **
. Lưu ý rằng nếu bạn tách ra việc khai báo và gọi hàm, nó sẽ trông như
char **arr;
...
arr = malloc(sizeof *arr * N);
Chúng tôi muốn gán kết quả của malloc
-arr
, không phải những gì arr
điểm để.
if (arr)
Có thể malloc
không thành công, vì vậy chúng tôi muốn kiểm tra kết quả trước khi sử dụng. Trong trường hợp malloc
không thành công, nó sẽ trả về giá trị con trỏ NULL.
{
size_t i;
for (i = 0; i < N; i++)
{
arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1));
Đối với mỗi con trỏ vật arr[i]
, chúng tôi phân bổ một khối bộ nhớ đủ lớn LENGTH + 1 yếu tố, mỗi đủ lớn để chứa một giá trị char
(sizeof *arr[i] == sizeof (char)
, vì loại *arr[i] == char
; lưu ý rằng sizeof (char)
luôn là 1) và gán kết quả cho arr[i]
.
Vì chúng tôi phân bổ từng chuỗi với một cuộc gọi malloc
riêng biệt, có thể chúng không tiếp giáp trong bộ nhớ. Đây là một bản đồ bộ nhớ cho thấy một thể kết quả của đoạn code trên: "* p1 == c, ví dụ: dereferencing p1 cho phép chúng ta đọc từ/viết thư cho c"
Item Address 0x00 0x01 0x02 0x03
---- ------- ---- ---- ---- ----
arr 0x80001000 0xA0 0xCC 0x00 0x00
...
arr[0] 0xA0CC0000 0xA0 0xCC 0x20 0x00
arr[1] 0xA0CC0004 0xA0 0xCC 0x20 0x40
arr[2] 0xA0CC0008 0xA0 0xCC 0x21 0x28
...
arr[19] 0xA0CC0014 0xA0 0xCC 0x23 0x10
...
arr[0][0] 0xA0CC2000 ' ' ' ' ' ' ' '
arr[0][4] 0xA0CC2004 ' ' ' ' ' ' ' '
arr[0][8] 0xA0CC2008 ' ' ' ' 0x00 0x??
...
arr[1][0] 0xA0CC2040 ' ' ' ' ' ' ' '
arr[1][4] 0xA0CC2044 ' ' ' ' ' ' ' '
arr[1][8] 0xA0CC2048 ' ' ' ' 0x00 0x??
...
Xin lỗi tôi là một người mới, vì vậy tôi có thể sai, nhưng để hoàn toàn làm sạch sau khi phân bổ, bạn sẽ phải lặp qua tổng số chuỗi và arr miễn phí [i ] cũng như giải phóng toàn bộ mảng miễn phí (arr), đúng không? Hoặc nó sẽ đủ để chỉ 'miễn phí (arr);'? –