2010-12-22 109 views
3

這是其中之一我認爲這應該工作,但最好檢查問題。它在我的機器上編譯和正常工作。作爲一個結構訪問數組*

這是保證做我所期望的(即允許我訪問數組的前幾個元素,保證結構的佈局,對齊,填充等與數組相同)?

struct thingStruct 
{ 
    int a; 
    int b; 
    int c; 
}; 


void f() 
{ 
    int thingsArray[5]; 
    struct thingStruct *thingsStruct = (struct thingStruct *)&thingsArray[0]; 

    thingsArray[0] = 100; 
    thingsArray[1] = 200; 
    thingsArray[2] = 300; 

    printf("%d", thingsStruct->a); 
    printf("%d", thingsStruct->b); 
    printf("%d", thingsStruct->c); 
} 

編輯:爲什麼地球上我會想要做這樣的事情?我有一個數組,我正在映射到一個文件。我將數組的第一部分視爲「標題」,它存儲有關數組的各種信息,其餘部分我將其視爲一個普通數組。如果我將結構指向數組的開始,我可以以結構成員的形式訪問這些頭部數據,這些結構更具可讀性。結構中的所有成員將與數組的類型相同。

+1

我認爲**只要您使用`#pragma`或其他東西來禁用結構上的填充。 – 2010-12-22 17:48:27

+0

請注意,您可以通過在結束定義的大括號後面添加__attribute __(packed)來完成GCC。 – 2010-12-22 18:23:09

+1

對於Windows編譯器(也受GCC支持),我相信你可以在結構定義之前使用`#pragma pack(0)`,之後使用`#pragma pack()`。 – 2010-12-22 18:23:53

回答

3

雖然我經常看到這樣做,但你不能(這意味着它不合法,標準C)對結構的二進制佈局做出假設,因爲它可能在字段之間有填充。

這在comp.lang.c常見問題進行了說明:http://c-faq.com/struct/padding.htmls

2

由於Evan對此問題發表了評論,如果您的結構中的所有類型都與您的數組類型相同,那麼在大多數情況下(如果您使用#pragma pack確保它們不是填充,可能最好) 。根據C的規則,這是合法的。

我對你的問題是「爲什麼?」這不是一件特別安全的事情。如果一個浮點數被扔進結構的中間,這一切都會崩潰。爲什麼不直接使用結構?這真的不是我在大多數情況下推薦的技術。

+1

「鑑於C的規則,這是合法的。」這是否違反嚴格的別名規則? – 2010-12-22 18:25:27

3

雖然這是可能在大多數地方工作,它仍然是一個有點玄乎。如果你想給符號名頭的部分,爲什麼不只是做:

enum { HEADER_A, HEADER_B, HEADER_C }; 

/* ... */. 

printf("%d", thingsArray[HEADER_A]); 
printf("%d", thingsArray[HEADER_B]); 
printf("%d", thingsArray[HEADER_C]); 
0

用於表示一個頭和文件數據的其餘部分另一種解決方案是使用結構是這樣的:

struct header { 
    long headerData1; 
    int headerData2; 
    int headerData3; 
    int fileData[ 1 ]; // <- data begin here 
}; 

然後你用一個文件的內容分配的內存塊,並與

myFileHeader->fileData[ position ] 

任意大投它作爲struct header *myFileHeader(或地圖上的一個文件的內存塊),並訪問您的所有文件數據position。該語言對索引值沒有限制,因此只有您有責任將您的任意大的posistion保留在您分配的內存塊的實際大小(或映射文件的大小)內。

還有一個重要提示:除了關掉結構成員的填充,已經由他人進行了說明,你應該仔細選擇頁眉成員的數據類型,讓他們儘管編譯器貼合實際的文件數據佈局你用(說,int將不會從32位更改爲64位...)

相關問題