2009-10-30 96 views
0

有沒有什麼辦法在C中創建一個可變大小的雙向腳本數組(不是C++,只是C)?我知道要創建一個可變大小的單腳本數組,你只需使用一個指針,例如C中的可變大小矩陣

float *array; 
array = (float *) calloc(sizeof(float), n); 

創建大小爲n的漂浮的單獨-腳本陣列。對於雙腳本陣列,我能做些類似的事嗎?

回答

10

C中沒有雙重腳本數組;只有數組數組。例如。這個:

int a[3][3]; 

應該讀作「3個數組的3個數組」,而不是「3x3個數組的數組」。這從表達的類型立即可見 - 例如, a[0]是一個有效的表達式,其類型爲int[3]

對於數組類型,數組大小是類型的一部分,因此必須在編譯時知道。因此,儘管你可以有一種類型的「指針數組」,使一名維動態,其餘的將仍然是固定的:

int (*p)[3] // pointer to arrays of 3 ints each 

有兩種傳統的解決方法:

  1. 剛使用一維寬度 x 高度元素的一維動態數組,並且自己計算2D座標中的1D索引爲(y * width + x)

  2. 使用指針的指針:

    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]; 
    ... 
} 
+1

在第二種方法中,您不需要爲數組的每一行都執行一個'malloc' - 您仍然可以將其分配到一個大塊中,然後將行指針分配給該分配中的位置。 – caf 2009-11-02 05:44:49

+0

爲選項1的額外的例子看到我的答案在這裏http://stackoverflow.com/questions/3063085/declaring-two-large-2d-arrays-gives-segmentation-fault/3063693#3063693 – Spudd86 2010-06-27 04:57:51

5

對於多維數組,您可以做幾乎相同的事情。

float **array; 
array = calloc(sizeof(float*), n); 
for(int i = 0; i < n; i++) 
{ 
    array[i] = calloc(sizeof(float), n); 
} 
+0

在這一點上,我將只能夠例如調用array [2] [3] = 5?當然,假設n> 3。 – wolfPack88 2009-10-30 17:21:09

+0

這有點誤導 - 一個二維數組'double [] []'佔據了一段單獨的內存,而它爲每一行存儲了一個指向數據段的指針數組。當然,你仍然可以通過數組下標訪問它,但它絕對不是同一件事。 – Cascabel 2009-10-30 17:23:50

+0

@ wolfPack88:是的,但要明白它是如何工作的。 'array [2]'是存儲在數組中的第三個「float *」指針,而'array [3]'將第四個'float'存儲在array [2]指向的內存中。 – Cascabel 2009-10-30 17:26:14

4

如果你想與n行和m列的矩陣然後可以使用長度m*n的線性陣列來表示這一點,其中每個索引i表示

row = i/n 
col = i % n 

和逆映射

i = row * n + col 

大多數使用像matlab這樣的矩陣的代數包實際上都使用這種表示,因爲它可以很好地推廣到任何維度(你c也應該將其推廣到一個三維矩陣)。

2

不,那是不可能的。作爲替代方案,分配單個數組,並定義一個索引函數,該函數接受您的座標並將索引返回到數組中。

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; 
+0

我想你的意思*(數據+ 34 * 200 + 56)= 42.0f ...我通常更喜歡更文化的風格。 「 – mch 2009-10-31 00:22:17

1

可以使用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); 
} 
+0

」您可以使用C99可變長度數組。「但請不要。 :) – BobbyShaftoe 2009-10-30 22:28:33

+0

@Bobby:我沒有看到一個理由,如果你的編譯器支持它們 - 特別是在這種情況下,不涉及堆棧分配...... – Christoph 2009-10-30 22:40:28

1

我很驚訝沒有人已經指出了「明顯的」替代其保留了單個連續分配主矩陣,但具有指向雙向下標的向量。顯然

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數組訪問如常分配。