2012-04-12 145 views
22

我正在寫C代碼,我想堆分配512 * 256字節。爲了我自己的方便,我希望能夠通過語法數組[a] [b]訪問元素;沒有算法找到正確的索引。堆分配一個二維數組(而不是指針數組)

我在網上看到的每個教程都告訴我要創建一個指向數組的行數組的指針數組。這意味着每個子數組需要單獨使用malloc和free。我感興趣的解決方案只需要一次調用malloc和一次調用即可(因此所有元素都是連續的)我認爲這是可能的,因爲我不會構造一個鋸齒形數組。

我將不勝感激任何人都可以分享聲明這樣一個數組的語法。

+1

是C++的一個選項?你可以創建一個簡單的C++對象來重載索引操作符。 – 2012-04-12 01:50:25

+4

@ RichardJ.RossIII:對於「我該如何在C中執行此操作?」這個問題,這真的是一個有效的迴應嗎? (意識到你*已*留下評論)。我會在任何一天C通過C++感謝你。 – 2012-04-12 01:56:13

+0

@EdS。雖然你可能更喜歡C,但在很多情況下C++更好,而這將是其中之一。我只是爲了確定它是否是一種選擇而留下評論。 – 2012-04-12 01:59:11

回答

34

那麼,如果你想分配數組類型,你可以將它分配到該類型的指針中。

由於二維數組是數組的數組(在你的情況下,512點的陣列256個字符數組),則應該將其分配到一個指針256個字符數組:

char (*arr)[256]=malloc(512*256); 
//Now, you can, for example: 
arr[500][200]=75; 

(周圍的括號*arr是使它成爲指向數組的指針,而不是指針數組)

+0

+1,不知怎的,我錯過了你在寫我的答案時發佈了這個消息。 :-) – 2012-04-12 02:50:34

+0

這正是我所期待的。謝謝。 – Paul 2012-04-12 08:21:48

+3

請注意,由於C99在編譯時不再需要知道尺寸。你可以從標準輸入讀取'n,m'並聲明一個'char arr [n] [m]',或者在這個例子中是'char(* arr)[n]'。 – Kos 2012-04-12 08:59:40

14

如果像這樣分配數組,它需要兩個對free的調用,但它允許array[a][b]樣式語法並且是連續的。

char **array = malloc(512 * sizeof(char *)); 
array[0] = malloc(512*256); 
for (int i = 1; i < 512; i++) 
    array[i] = array[0] + (256 * i); 

array2這裏瞭解更多信息:http://c-faq.com/aryptr/dynmuldimary.html

+0

這是一個不錯的訣竅! +1 – 2012-04-12 01:53:55

+3

您可以通過將數據塊立即放置在塗料載體之後來合併兩個分配。需要一定數量的繁瑣類型轉換,但並不困難。然而,你所顯示的代碼有一個嚴重的錯誤:你爲512個char分配了空間,然後你認爲這個空間足夠512 * char *的空間。這只是保證走出分配和崩潰的結尾。 – zwol 2012-04-12 01:55:37

+0

糟糕的錯字,應該這樣做...... – 2012-04-12 02:01:33

5

既然你知道數組的大小,時間提前,你可以創建一個包含521x256陣列struct類型,然後動態分配struct

2

如果你知道這個數組的大小,你可以typedef它,併爲它做一個指針。下面是說明了這一點使用一小片段:

#include <stdio.h> 
#include <stdlib.h> 

typedef int array2d[20][20]; 

int main() { 
    int i,j; 
    array2d *a = malloc(sizeof(array2d)); 
    for(i=0;i!=20;i++) 
     for(j=0;j!=20;j++) 
      (*a)[i][j] = i + j; 

    for(i=0;i!=20;i++) 
     for(j=0;j!=20;j++) 
      printf("%d ",(*a)[i][j]); 
    free(a); 
    return 0; 
} 
+0

有趣的解決方案,有沒有什麼辦法可以弄清楚如何用動態數組來做到這一點? – 2012-04-12 02:02:02

+0

@ RichardJ.RossIII不幸的是,這不適用於動態大小的數組,因爲typedef需要兩個維度的編譯時常量。你可以做的最好的做法是使一個維度固定,另一個維度動態,但它不會使其完全動態。 – dasblinkenlight 2012-04-12 02:05:28

+0

typedef是不必要的,實際上它將兩個維都放在typedef中是有害的,因爲你使用'(* a)'而不是簡單的'a'來卡住。如果你只是把列數,它會更好。當然,對於C99,您可以對類型進行可變更改;我相信這在typedef中是有效的,只要typedef具有塊範圍而不是文件範圍。 – 2012-04-12 02:49:53

2

可以動態地分配相同類型的多維數組

static char x[512][256]; 

給你的,但它是一個凌晨棘手,因爲類型衰變。我只知道如何與typedef做到這一點:

typedef char row[512]; 
row *x = malloc(sizeof(row) * 256); 

這隻會讓你在運行時確定第二尺寸的大小。如果兩個維度在運行時可能有所不同,則需要一個dope向量。

+0

也錯過了這一個。請注意,除非您僅限於C89,否則兩個尺寸都可能有所不同;你只需要使用可變修改的指針類型。 – 2012-04-12 02:51:23

11

假設您不需要與古老的C89標準兼容(在當前的C編譯器中,只有MSVC和一些嵌入式目標編譯器是倒退的)。這裏是你如何做到這一點:

int (*array)[cols] = malloc(rows * sizeof *array); 

然後array[a][b]的有效期爲在[0,rows)[0,cols)任何ab

在C語言標準中,array可變修改類型。如果要將指針傳遞給其他函數,則需要在函數參數列表中重複使用此類型,並確保至少將列數傳遞給該函數(因爲需要將其作爲可變更改的一部分類型)。

編輯:我錯過了一個事實,即OP只關心一個固定的大小,512x256。在這種情況下,C89就足夠了,和所有你需要的是:

int (*array)[256] = malloc(512 * sizeof *array); 

完全相同的類型可以在函數參數列表中使用,如果你需要的是傳遞函數的指針(也爲函數返回類型,但爲了這個用途,你可能想要typedef它... :-)

+0

你在一般情況下是正確的,但OP只要512 * 256陣列。 – asaelr 2012-04-12 02:43:14

+0

的確,我會更新答案。 – 2012-04-12 02:44:41

+0

其實這個答案非常好。雖然我現在只需要512 * 256,但我可以很容易地看到這個需求在未來會發生變化。 – Paul 2012-04-16 16:43:30