因此,對於操縱一個2D VLA的函數,你會喜歡寫東西
void foo(size_t rows, size_t cols, int (*multiarray)[cols]) // or multiarray[][cols]
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
multiarray[i][j] = some_value();
}
怎麼了int (*multiarray)[cols]
?請記住,在將數組表達式作爲參數傳遞時,數組表達式的類型將從「N元素數組T
」轉換爲「指向T
」。在這種情況下,T
爲「cols
的int
- 元素陣」,讓我們從「的int
cols
- 元素阿雷的rows
- 元素陣列」到「指針cols
的int
- 元素陣列」去。在函數參數聲明的上下文中,T a[N]
,T a[]
和T *a
都是相同的;在所有三種情況下,a
被宣佈爲指針至T
。所以int (*multiarray)[cols]
相當於int multiarray[][cols]
,相當於int multiarray[rows][cols]
。我更喜歡使用第一種形式,因爲它最準確地代表了情況。
如果你想這個數組作爲參數傳遞給另一個函數,你會使用相同類型:
void bar(size_t rows, size_t cols, int (*multiarray)[cols])
{
foo(rows, cols, multiarray);
}
int main(void)
{
size_t rows = 0;
size_t cols = 0;
// you must assign values to rows and cols before declaring a VLA with them
rows = ...;
cols = ...;
int arr[rows][cols];
bar(rows, cols, arr);
...
}
在foo
所做的數組內容的任何更改將反映在bar
和main
。
VLA可能有用,但它們有其侷限性。它們不能被聲明爲static
,它們也不能在函數之外定義。他們不能使用{}
式初始化語法。此外,VLA支持現在是2011年標準的可選,所以您不能依賴於它們在任何地方的支持。
如果您沒有可用的VLA,並且您的陣列大小在運行時才知道,則必須使用動態內存分配(malloc
或calloc
),並且您傳遞給函數的類型將爲不同:這種方法
void foo(size_t rows, size_t cols, int **multiarray)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
multiarray[i][j] = some_value();
}
void bar(size_t rows, size_t cols, int **multiarray)
{
foo(rows, cols, multiarray);
}
int main(void)
{
size_t rows;
size_t cols;
int **multiarray = NULL;
... // get rows and cols
// allocate memory for pointers to each row
multiarray = malloc(sizeof *multiarray * rows);
if (multiarray)
{
size_t i;
// allocate each row
for (i = 0; i < rows; i++)
{
multiarray[i] = malloc(sizeof *multiarray[i] * cols);
if (!multiarray[i])
break;
}
if (i < rows)
{
// malloc failed for one of the multiarray rows; we need to
// free whatever memory has already been allocated and exit
while (i--)
free(multiarray[i]);
free(multiarray);
exit(0);
}
}
bar (rows, cols, multiarray);
...
if (multiarray)
{
size_t i;
for (i = 0; i < rows; i++)
free(multiarray[i]);
free(multiarray);
}
}
一個缺點是,所分配的存儲器不能保證是連續的(即,行不會在存儲器相鄰的)。如果那件事情,你必須去與另一個方法。相反,單獨分配的行和列,你在一個單獨的塊分配的一切,並手動映射數組索引:
void foo(size_t rows, size_t cols, int *fakemultiarray)
{
size_t i, j;
for (i = 0; i < rows; i++)
for (j = 0; j < rows; j++)
fakemultiarray[ i * rows + j ] = some_value();
}
void bar(size_t rows, size_t cols, int *fakemultiarray)
{
foo(rows, cols, fakemultiarray);
}
int main(void)
{
size_t rows;
size_t cols;
int *fakemultiarray = NULL;
... // get rows and cols
fakemultiarray = malloc(sizeof *fakemultiarray * rows * cols);
if (fakemultiarray)
bar(rows, cols, fakemultiarray);
...
free(fakemultiarray);
}
在這種情況下,我們分配一個緩衝區足夠大的所有元素,但我們必須將其索引爲一維數組,計算索引爲i * rows + j
。
你沒有定義ROWS和COLUMNS? – Lucas
@Lucas不,我did.I只是編輯問題 – Dchris
在你的第二個例子中,你永遠不會定義行和列的大小。另外,主要局部變量影響全局定義。 – Lucas