有沒有什麼辦法在C中創建一個可變大小的雙向腳本數組(不是C++,只是C)?我知道要創建一個可變大小的單腳本數組,你只需使用一個指針,例如C中的可變大小矩陣
float *array;
array = (float *) calloc(sizeof(float), n);
創建大小爲n的漂浮的單獨-腳本陣列。對於雙腳本陣列,我能做些類似的事嗎?
有沒有什麼辦法在C中創建一個可變大小的雙向腳本數組(不是C++,只是C)?我知道要創建一個可變大小的單腳本數組,你只需使用一個指針,例如C中的可變大小矩陣
float *array;
array = (float *) calloc(sizeof(float), n);
創建大小爲n的漂浮的單獨-腳本陣列。對於雙腳本陣列,我能做些類似的事嗎?
C中沒有雙重腳本數組;只有數組數組。例如。這個:
int a[3][3];
應該讀作「3個數組的3個數組」,而不是「3x3個數組的數組」。這從表達的類型立即可見 - 例如, a[0]
是一個有效的表達式,其類型爲int[3]
。
對於數組類型,數組大小是類型的一部分,因此必須在編譯時知道。因此,儘管你可以有一種類型的「指針數組」,使一名維動態,其餘的將仍然是固定的:
int (*p)[3] // pointer to arrays of 3 ints each
有兩種傳統的解決方法:
剛使用一維寬度 x 高度元素的一維動態數組,並且自己計算2D座標中的1D索引爲(y * width + x)
。
使用指針的指針:
int** a = malloc(sizeof(int*) * height);
for (i = 0; i < height; ++i) a[i] = malloc(sizeof(int) * width);
a[0][0] = 123;
...
這裏的問題是,你的陣列不需要是長方形了,而你真的不能強制執行。在性能方面,它比單個連續的內存塊更差。
在C99中,你也可以使用變長數組:
void foo(int width, int height) {
int a[width][height];
...
}
comp.lang.c FAQ在此有一個很好的部分。
對於多維數組,您可以做幾乎相同的事情。
float **array;
array = calloc(sizeof(float*), n);
for(int i = 0; i < n; i++)
{
array[i] = calloc(sizeof(float), n);
}
在這一點上,我將只能夠例如調用array [2] [3] = 5?當然,假設n> 3。 – wolfPack88 2009-10-30 17:21:09
這有點誤導 - 一個二維數組'double [] []'佔據了一段單獨的內存,而它爲每一行存儲了一個指向數據段的指針數組。當然,你仍然可以通過數組下標訪問它,但它絕對不是同一件事。 – Cascabel 2009-10-30 17:23:50
@ wolfPack88:是的,但要明白它是如何工作的。 'array [2]'是存儲在數組中的第三個「float *」指針,而'array [3]'將第四個'float'存儲在array [2]指向的內存中。 – Cascabel 2009-10-30 17:26:14
如果你想與n行和m列的矩陣然後可以使用長度m*n
的線性陣列來表示這一點,其中每個索引i
表示
row = i/n
col = i % n
和逆映射
i = row * n + col
大多數使用像matlab這樣的矩陣的代數包實際上都使用這種表示,因爲它可以很好地推廣到任何維度(你c也應該將其推廣到一個三維矩陣)。
不,那是不可能的。作爲替代方案,分配單個數組,並定義一個索引函數,該函數接受您的座標並將索引返回到數組中。
int Index(int i, int j, int numCols)
{
return i * numCols + j;
}
int numRows = 100;
int numCols = 200;
float *data = malloc(sizeof(float) * numRows * numCols);
data[Index(34, 56, numCols)] = 42.0f;
我想你的意思*(數據+ 34 * 200 + 56)= 42.0f ...我通常更喜歡更文化的風格。 「 – mch 2009-10-31 00:22:17
可以使用C99可變長度數組(用gcc作品):
#include <stdio.h>
#include <stdlib.h>
void foo(size_t rows, size_t cols, float array[rows][cols])
{
printf("%f\n", array[2][3]);
}
int main(void)
{
size_t rows = 4;
size_t cols = 5;
float (*array)[cols] = calloc(sizeof (float), rows * cols);
array[2][3] = 42;
foo(rows, cols, array);
}
」您可以使用C99可變長度數組。「但請不要。 :) – BobbyShaftoe 2009-10-30 22:28:33
@Bobby:我沒有看到一個理由,如果你的編譯器支持它們 - 特別是在這種情況下,不涉及堆棧分配...... – Christoph 2009-10-30 22:40:28
我很驚訝沒有人已經指出了「明顯的」替代其保留了單個連續分配主矩陣,但具有指向雙向下標的向量。顯然
array2d[0][0] = 123.0;
,我們還需要檢查內存:(我想這意味着它並不明顯,畢竟)
float **array2d = malloc(sizeof(*array2d) * height);
float *array1d = malloc(sizeof(*array1d) * height * width);
for (i = 0; i < height; ++i)
array2d[i] = &array1d[i * width];
現在你可以寫2-d數組訪問如常分配。
在第二種方法中,您不需要爲數組的每一行都執行一個'malloc' - 您仍然可以將其分配到一個大塊中,然後將行指針分配給該分配中的位置。 – caf 2009-11-02 05:44:49
爲選項1的額外的例子看到我的答案在這裏http://stackoverflow.com/questions/3063085/declaring-two-large-2d-arrays-gives-segmentation-fault/3063693#3063693 – Spudd86 2010-06-27 04:57:51