注意:本文中使用的示例旨在解釋這些概念。因此,這些示例可能不完整,可能缺少錯誤處理等。
當涉及到在C
中使用多維數組時,以下是兩種可能的方法。
陣列
在C
扁平化的,陣列被實現爲一個連續存儲器塊。這些信息可以用來處理存儲在數組中的值,並允許快速訪問特定的數組位置。
例如,
int arr[10][10];
int *ptr = (int *)arr ;
ptr[11] = 10;
// this is equivalent to arr[1][0] = 10; assign a 2D array
// and manipulate now as a single dimensional array.
利用陣列的鄰接的性質被稱爲flattening of arrays
的技術。
襤褸陣列
現在,考慮下面的例子。
char **list;
list[0] = "United States of America";
list[1] = "India";
list[2] = "United Kingdom";
for(int i=0; i< 3 ;i++)
printf(" %d ",strlen(list[i]));
// prints 24 5 14
這種類型的實現被稱爲粗糙陣列,並且其中可變大小的字符串被用來在地方是有用的。流行的方法是在每個維度上完成dynamic-memory-allocation
。
注意:命令行參數(char *argv[]
)僅作爲不齊的數組傳遞。
比較扁平且粗糙的陣列
現在,讓我們考慮下面的代碼片斷,其比較所述flattened
和ragged
陣列。
/* Note: lacks error handling */
int flattened[30][20][10];
int ***ragged;
int i,j,numElements=0,numPointers=1;
ragged = (int ***) malloc(sizeof(int **) * 30);
numPointers += 30;
for(i=0; i<30; i++) {
ragged[i] = (int **)malloc(sizeof(int*) * 20);
numPointers += 20;
for(j=0; j<20; j++) {
ragged[i][j]=(int*)malloc(sizeof(int) * 10);
numElements += 10;
}
}
printf("Number of elements = %d",numElements);
printf("Number of pointers = %d",numPointers);
// it prints
// Number of elements = 6000
// Number of pointers = 631
從上面的例子中,ragged
陣列需要631-pointers
,換句話說,用於指向6000
整數631 * sizeof(int *)
額外的存儲器位置。而flattened
數組只需要一個基址指針:即數組名稱足以指向連續的6000
存儲位置。
但是OTOH,ragged
陣列是靈活的。在不知道所需存儲位置的確切數量的情況下,您無法爲最壞的情況分配內存。同樣,在某些情況下,只有在運行時才知道所需的確切存儲空間數量。在這種情況下,ragged
陣列變得非常方便。
行優先和陣列的列優先
C
如下row-major
排序爲多維陣列。在C
中,陣列的Flattening
可被視爲由於此方面的影響。 C的row-major
的意義在於它適合在編程中進行大部分訪問的自然方式。例如,讓我們來看一個例子用於穿越N * M
2D矩陣,
for(i=0; i<N; i++) {
for(j=0; j<M; j++)
printf(「%d 」, matrix[i][j]);
printf("\n");
}
矩陣中的每行被訪問一個接一個,由快速變化的列。這種自然的方式將C
陣列排列在內存中。相反,請考慮以下示例,
for(i=0; i<M; i++) {
for(j=0; j<N; j++)
printf(「%d 」, matrix[j][i]);
printf("\n");
}
這會比列索引更頻繁地更改列索引。正因爲如此,這兩個代碼片段之間的效率差別很大。是的,第一個比第二個更有效率!
因爲第一個按照C的自然順序(row-major
順序)訪問數組,所以它更快,而第二個需要更多的時間來跳轉。隨着尺寸數量和元件尺寸的增加,性能差異會變寬。
所以當在C
中使用多維數組時,很好考慮上面的細節!
你想用數據做什麼?不知道你在做什麼,很難告訴你該做什麼。 – user1118321 2012-01-07 00:33:38