Như những người khác đã chỉ ra, một mảng đa chiều là một mảng các mảng, không phải là một mảng các con trỏ.
Tôi nghĩ nguyên nhân chính gây hiểu lầm là khái niệm về bất kỳ mảng nào thực sự là một con trỏ.Nhưng nó không đúng. Một mảng là một biến chứa một bộ sưu tập liên tục có kích thước cố định của các phần tử cùng loại. Vì vậy, khi bạn khai báo một mảng như int x[2]
bạn đang khai báo một biến chứa hai số nguyên. Lưu ý rằng nó không giữ bất kỳ con trỏ nào. Bây giờ gốc của sự hiểu lầm phổ biến này là trong C/C++ một tên mảng đánh giá đến địa chỉ của phần tử đầu tiên của nó và do đó có thể được sử dụng như một con trỏ. Nói cách khác, khi bạn viết x
, nghĩa là bạn ngụ ý &x
hoặc &x[0]
. Điều này có thể được thực hiện để làm cho các biểu thức dễ đọc hơn.
Mảng đa chiều chỉ đơn giản là mảng mảng. Nói cách khác, cùng một logic áp dụng cho họ, không có gì đặc biệt cả. Bạn đọc khai báo C/C++ bắt đầu từ tên và đi ra ngoài, áp dụng các công cụ sửa đổi khi bạn gặp chúng, đầu tiên [] và(), sau đó *, sau đó nhập, do đó bạn diễn giải một mảng đa chiều như thế này (thứ tự đọc được xác định rõ ràng)):
int x [ 2] [ 5];
6. "of type int" 1. "x" 2. "is an array" 3. "of 2". 4. "arrays" 5. "of 5 elements"
vì vậy, không có những điều như mảng đa chiều trong C/C++, nhưng có những điều như mảng một chiều của mảng một chiều. Theo các quy tắc cho mảng một chiều, x
, &x
và &x[0]
tất cả các đánh giá về địa chỉ của phần tử đầu tiên. Nhưng vì phần tử đầu tiên là một mảng, x[0]
đánh giá địa chỉ của mảng đó, tức là địa chỉ của phần tử đầu tiên của nó là một phần tử int. Điều tương tự cũng xảy ra với &x[0]
và &x[0][0]
. Đó là lý do tại sao giá trị của x[0]
giống với địa chỉ của nó - bởi vì x[0]
là một mảng.
Lưu ý rằng mặc dù những thứ này được đánh giá theo cùng một địa chỉ nhưng chúng có các loại khác nhau. x
là một con trỏ tới một mảng gồm 5 ints, cũng như &x[0]
, vì cả hai đều đánh giá đến địa chỉ của phần tử đầu tiên của x. x[0]
đánh giá đến địa chỉ của phần tử đầu tiên là x[0]
, do đó, đó là con trỏ đến int, tương tự với số &x[0][0]
. Ví dụ này biên dịch tốt và in cùng một địa chỉ cho tất cả 4 con trỏ:
int x[2][5];
int (*y1)[5] = x;
int *y2 = x[0];
int (*y3)[5] = &x[0];
int *y4 = &x[0][0];
printf("%p %p %p %p\n", y1, y2, y3, y4);
Bây giờ, có các bố trí bộ nhớ khác nhau cho mảng được sử dụng bằng các ngôn ngữ khác nhau. Ví dụ, đối với mảng hai chiều, bạn có thể nhóm các phần tử theo hàng hoặc theo cột. Trong C/C++, vì không có mảng đa chiều "thực", bố trí bộ nhớ được xác định ngầm bởi các quy tắc trên. Kể từ int x[2][5]
, có thể được coi là mảng hai chiều có 2 hàng và 5 cột, thực sự là một mảng gồm 2 mảng, mỗi mảng đại diện cho một hàng, bạn sẽ có bố cục "nhóm theo hàng", được trình bày trong câu trả lời của shybovycha.
Lưu ý rằng bạn cũng có thể tạo một mảng con trỏ và sử dụng nó làm mảng đa chiều. Sự khác biệt đối với mảng đa chiều "thông thường" là:
- Một chuỗi con trỏ thực sự chứa con trỏ bên trong. Đó là, địa chỉ của các phần tử đầu tiên của mảng phụ.
- Bố cục bộ nhớ không tiếp giáp. Mỗi mảng phụ có thể được cấp phát ở mọi nơi, ví dụ bằng cách sử dụng malloc() hoặc new [].
- Các mảng phụ có thể có kích thước khác nhau.
Lợi thế của cách tiếp cận này là bạn có thể sử dụng mảng này làm con trỏ trỏ tới con trỏ (ví dụ: int **y
), làm cho tất cả các mảng đa chiều tương thích với nhau. kích cỡ.Nhưng kích thước phải được lưu trữ riêng trong trường hợp này.
Vui lòng đọc http://c-faq.com/aryptr/index.html –
Bạn có thể đọc [FAQ] (http://stackoverflow.com/questions/4810664/) về cách sử dụng mảng trong C++;) – fredoverflow