2015-10-25 12 views
8

Tại sao nó không phải là cần thiết để đề cập đến khía cạnh đầu tiên của mảng đa chiều và cần thiết để đề cập đến khía cạnh khác:Tại sao nó được phép bỏ qua thứ nguyên đầu tiên, nhưng không được phép sử dụng các tham số khác khi khai báo mảng đa dimensonal?

int A[][][2]={{{1,2},{3,4}},{{4,5},{5,6}}}; // error 
int A[][2][2]={{{1,2},{3,4}},{{4,5},{5,6}}}; // OK 

Tôi không thể hiểu được khái niệm hoặc logic đằng sau này.

+3

Bạn có thể trình bày mẫu mã chính xác bạn đang nói không. –

+1

Thông thường, mọi người đang đặt câu hỏi này bởi vì họ định truyền một mảng đa chiều làm tham số cho một hàm và họ muốn hàm xử lý bất kỳ kích thước mảng nào. Nếu đó là trường hợp của bạn, tôi khuyên bạn nên sử dụng vectơ để thay thế. – Christophe

+0

int A [] [] [2] = {{{1,2}, {3,4}}, {{4,5}, {5,6}}} tại đây có lỗi int A [] [ 2] [2] = {{{1,2}, {3,4}}, {{4,5}, {5,6}}} tại đây tốt đẹp –

Trả lời

4

Cần phải đề cập đến cả hai chiều của mảng 2D ngoại trừ khi nó nằm trong tham số của hàm hoặc nếu có trình khởi tạo thì có thể bỏ qua thứ nguyên đầu tiên.

Khi được sử dụng như một tham số trong một chức năng, ví dụ,

int 2D_arr[m][n] 

chuyển đổi sang

int (*2D_arr)[n] 

Như vậy, kích thước đầu tiên có thể được bỏ qua. Tuy nhiên, thứ nguyên thứ hai phải có để cho trình biên dịch biết rằng con trỏ 2D_arr là một con trỏ đến một mảng của n ints.

Trong trường hợp thứ hai, khi khởi tạo hiện diện

int A[][2][2]={{{1,2},{3,4}},{{4,5},{5,6}}};  

trình biên dịch sử dụng độ dài của initializer để tính toán kích thước đầu tiên mà thôi. Phần còn lại của thứ nguyên phải được chỉ định rõ ràng tại thời điểm khai báo.

+1

Tôi nghĩ rằng anh ta hỏi tại sao nhiều kích thước hơn không thể được suy ra khi initializers có mặt –

+1

@ M.M; Câu hỏi của ông không rõ ràng. – haccks

5

Vì khi sử dụng mảng đa chiều, việc tính toán chỉ mục thực tế sử dụng tất cả các kích thước thứ nguyên ngoại trừ kích thước đầu tiên. Ví dụ cho một mảng 3D khai báo là int arr[3][4][5];, arr[i][j][k]theo định nghĩa*(&(arr[0][0][0]) + k + 5 *(j + 4 * i))

Vì vậy, khi kích thước đầu tiên có thể được rút ra từ việc khởi tạo bối cảnh, hoặc có thể được bỏ qua (khi nhận được một tham số trong một funtion) nó có thể được bỏ qua.

Ví dụ:

int arr[][2] = { 1,2,3,4 }; 

void setArr(void *container, int arr[][4]); 
+0

Đây là điểm cơ bản, nhưng có thể rõ ràng hơn khi nói rằng dereferencing mảng 'arr [i] [j] [k]' là "tương đương với" 'arr [i] [j] [k] = * (& (arr [0] [0] [0]) + k + 5 * (j + 4 * i)); 'thay vì hiển thị nó như là một phần của cùng mã với khai báo vì bạn không phải viết loại đó của dòng trong nhiều ứng dụng hơn. Và nếu đó là câu trả lời của tôi, tôi sẽ đặt tên cho các kích thước mảng bởi vì nó rất dễ đọc theo cách đó mà không cần tham khảo lại tờ khai. – dmckee

+0

@dmckee: bạn nói đúng. Tôi đã không nhận ra nó xuất hiện như mã ... Post edited. –

1

Nếu bạn khai báo một mảng 2D một cách tĩnh ...

int arr[3][4]; 

... sau đó hai kích thước của nó là hiển nhiên.

Nếu bạn khai báo một mảng 2D một cách năng động, hoặc là một con trỏ đến con trỏ ...

int r = 3, c = 4; 
int** arr = new int*[r]; 
for (int i = 0; i < r; i++) { 
    arr[i] = new int[c]; 
} 

... nó trông như thể chỉ có một chiều được đề cập trong phân bổ nhưng đó là bởi vì trước hết bạn phân bổ các hàng và sau đó mỗi cột. Khi bạn nhận hoặc đặt một phần tử, bạn chỉ định cả hai thứ nguyên như thông thường ...

num = arr[1][2]; 
arr[1][2] = num; 
Các vấn đề liên quan