2011-01-30 22 views
5

Tôi gặp rất nhiều vấn đề tìm hiểu mảng đa chiều Hãy để một mảng đượcmảng đa chiều trong C++, một bí ẩn đối với tôi :(

x[2]; // now x is constant pointer to first element i.e x's name is address of x[0] 

Bây giờ hai chiều mảng:.

x[2][5]; // here x is address of x[0] which contains the address of first element of array x[][0]; 

Bây giờ con trỏ

int(*y)[5]; 

là con trỏ tới mảng 5 của số nguyên. Làm cách nào để viết y = x?

Bây giờ tôi đang làm một số thực tế để hiểu được điều này trong VS, mà là ở đây, và câu hỏi chính của tôi là trong hình ảnh:

http://img184.imagevenue.com/img.php?image=96382_first_122_1120lo.jpg

Hãy trả lời câu hỏi khái niệm; cách C++ cửa hàng mảng đa chiều vv

tôi sẽ đánh giá cao bất kỳ sự giúp đỡ rất nhiều :)

+0

Vui lòng đọc http://c-faq.com/aryptr/index.html –

+1

Bạn có thể đọc [FAQ] (http://stackoverflow.com/questions/4810664/) về cách sử dụng mảng trong C++;) – fredoverflow

Trả lời

6

Look: bất kỳ mảng đa chiều là mảng của mảng. Ví dụ. x[2][5] sẽ bằng bảng này:

x[0][0]x[0][1]x[0][2]x[0][3]x[0][4]

x[1][0]x[1][1]x[1][2]x[1][3]x[1][4]

gán con trỏ sẽ giống hệt nhau: x[0] là dòng đầu tiên trong bảng 2x5 của bạn, vì vậy int *y = x[0] hoặc int *y = x[1] sẽ sao chép địa chỉ của hàng đầu tiên đến y.

Nhưng nếu bạn làm int (*y) = x sau đó nó sẽ lưu địa chỉ của x[0][0] vào y biến (int y tạo ra một thể hiện int khi int (*y) cung cấp cho bạn địa chỉ của trường hợp này).

UPD: Hãy để chúng tôi có int **x biến. Nó không quan trọng kích thước của nó. Chỉ cần coi đây là sự thật là x, x[0]x[0][0] sẽ cung cấp cho bạn cùng một địa chỉ. Điều này có thể được giải thích như Pointer name means its address. Multi-dimensional array is a pointer to pointer. Its name means address of pointer it's pointing on which means address of the last pointer' first element. (xin lỗi vì sự phức tạp).

+0

+1 cho số lượng ví dụ –

3

Vì tên mảng một chiều được coi là con trỏ đến phần tử đầu tiên, cấu trúc x [0] là con trỏ tới mảng đầu tiên của mảng 2d và x [1] là con trỏ vào mảng thứ hai của bạn. Vì vậy, chỉ cần nghĩ về x [0] vì nó là tên của mảng thứ nhất của bạn. Việc thêm một cặp ngoặc đơn khác (như x [0] [0]) sẽ trả về giá trị của phần tử. Và địa chỉ của phần tử đầu tiên sẽ là & x [0] [0] hoặc chỉ đơn giản là x [0].

7

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&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]&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à:

  1. 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ụ.
  2. 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 [].
  3. 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.