2014-03-19 49 views
0

我真的不知道如何正確地爲頭文件中定義的結構數組分配內存。 頭的代碼如下所示:爲結構數組分配內存(在頭文件中定義)

header.h

typedef struct _Transform Transform; 

header.c

struct _Transform{ 
    char c; 
    //the actual operation which is an union 
    Operation o; 
}; 

應該在我的主要程序做這樣的事情?

program.c

#include "header.h" 

Transform **transform = calloc(MAX_NO_OF_TRANSFORMS, sizeof(Transform*)); 
if(!transform) { 
    perror("Error allocating memory for transform"); 
    exit(EXIT_FAILURE); 
} 
for(i = 0; i < MAX_NO_OF_TRANSFORMS; i++) 
    transform[i] = calloc(1, sizeof(Transform*)); 

如果是這樣,我應該怎麼再打電話了嗎?我有一個錯誤,當我嘗試調用

transform[0].c = 'a'; 

順便說一句,頭被正確連接和工作。 謝謝!

+1

你想要它靜態分配,還是動態?你想要一個一維數組還是二維數組?請澄清。分配一個'struct _Transform'數組就像'struct Transform array [ARRAY_LENGTH]'一樣簡單,但是從你的代碼看起來你需要別的東西。 –

+0

對不起,我想要一個1D數組,但是我不能進行Transform數組[ARRAY_LENGTH],因爲struct是在頭中定義的。 –

+0

你爲什麼不能?只要'struct _Transform'的定義在範圍內,就可以聲明它的一個數組。您可以包含標題,然後在源文件中將該數組聲明爲'Transform transform [MAX_NO_OF_TRANSFORMS]'。在這種情況下使用動態內存過於誇張,尤其是因爲您似乎在編譯時已知數組大小的上限。 –

回答

2

如果沒有範圍內的結構定義,將永遠無法在program.c中聲明數組。頭文件沒有提供足夠的信息來使編譯器知道Transform的大小,所以你不能在program.c中聲明它的數組。

指針指向Transform的指針的分配工作,因爲編譯器不需要知道Transform的大小,因爲指向的對象本身就是一個指針。

將結構定義移動到頭文件中。換句話說,header.h應該是:

header.h

struct _Transform{ 
    char c; 
    //the actual operation which is an union 
    Operation o; 
}; 

typedef struct _Transform Transform; 

而現在,在program.c,你可以聲明靜態分配的數組,像這樣:

Transform transform[MAX_NO_OF_TRANSFORMS]; 

沒有需要在代碼中使用動態分配的內存;考慮到我們在評論部分的討論,這是過分的,完全沒有必要。

UPDATE

因爲你似乎是新的這種東西,我會給你一個提示:請始終使用包含在你的頭文件警衛,以避免編譯器因多次包含奇怪的錯誤。例如,如果在program.c中包含header1.hheader2.h,並且header2.h中已包含header1.h,則在編譯program.c(就好像您包含同一個文件兩次)時將會出現多個定義錯誤。包括警衛可以防止這種情況發生。一個典型用法是這樣的:

header.h

#ifndef TRANSFORM__STRUCT__HEADER 
#define TRANSFORM__STRUCT__HEADER 
struct _Transform{ 
    char c; 
    //the actual operation which is an union 
    Operation o; 
}; 

typedef struct _Transform Transform; 
#endif 

這是一種廣泛使用的技術。基本上,它通過在第一次包含文件時定義預處理器符號起作用 - 如果再次包含該文件,#ifndef將評估爲false,並且不包含任何內容。

+0

哇你真的幫我了!我從來不知道你可以在header.h文件中做到這一點。我認爲所有的定義應該在header.c中; 我不知道這件事。你解決了我的兩個問題。謝謝! :) –

+0

你從現在開始讓我的工作更輕鬆! :) –

+0

@SebastianLuke你可以在頭文件中做很多事情。通常,在多個源文件之間共享的結構定義必須放置在頭文件中,幷包含在源文件中。我也用已知的解決方法更新我的答案,以避免多次包含相同的文件。 –

0

您的代碼有幾個問題。首先,下面的語句

transform[i] = calloc(1, sizeof(Transform *)); 

分配內存的指針堅持一個Transform對象,而不是Transform對象本身。

其次,sizeof在編譯期間運行,除了變長數組對象。文件program.c範圍內的類型名稱Transform是不完整的類型,因爲如果沒有在鏈接階段解析其定義,則無法確定其大小。您應該將結構定義移動到header.h文件。您可以修改program.c

// program.c 

// dynamically allocate an array to hold pointers to Transform objects 

Transform **transform = calloc(MAX_NO_OF_TRANSFORMS, sizeof *transform); 
if(!transform) { 
    perror("Error allocating memory for transform"); 
    exit(EXIT_FAILURE); 
} 



for(i = 0; i < MAX_NO_OF_TRANSFORMS; i++) { 
    // allocate memory to hold Transform objects and make the array element 
    // point to it. You can also replace **transform with *transform[i] in 
    // the calloc call. 

    transform[i] = calloc(1, sizeof **transform); 

    // check for NULL 
    if(transform[i] == NULL) { 
     perror("Error in allocating memory"); 
     // handle it 
    } 
} 
+1

'sizeof * Transform'不會編譯 - 也許你的意思是'sizeof * transform'。而'sizeof(Transform)'會比'sizeof ** transform'更好。 –

+0

錯誤:將'sizeof'應用於不完整類型'Transform'| –

+0

@SebastianLuke對不起。已經更新了我的答案。請再試一次。 – ajay

0

塞巴斯蒂安,

此:

transform[i] = calloc(1, sizeof(Transform*)); 

應改爲:

transform[i] = calloc(1, sizeof(Transform)); 

您需要分配足夠的內存來存儲記錄 - 第一種方式,你只需爲指向Transform的指針分配足夠的內存。

+0

我認爲是這樣,但我得到這個回報: 錯誤:'sizeof'的不適用應用於不完整類型'轉換'| –

+0

您必須使用typedef,正如其他人所建議的那樣。 –

+0

從我寫結構的第一刻起,我用typedef :)後來我發現問題是什麼,但仍然是:謝謝! :) –