2012-06-05 33 views
4

我有兩個不同的數據結構,原則上應該有相同的大小,我想知道他們爲什麼不這樣做。Windows 64位結構大小因所含數據類型而異?

struct pix1 { 
    unsigned char r; 
    unsigned char g; 
    unsigned char b; 
    unsigned char a; 
    unsigned char y[2]; 
}; 

struct pix2 { 
    unsigned char r; 
    unsigned char g; 
    unsigned char b; 
    unsigned char a; 
    unsigned short y; 
}; 

然後,這些像素的I組4一起,因爲這樣的:

struct pix4 { 
    pix1 pixels[4]; // or pix2 pixels[4] 
    unsigned char mask; 
}; 

...但事實證明,這樣的分組的改變的大小,根據的sizeof(PIX4),取決於我是否使用pix1或pix2。個人sizeof(pix1)== sizeof(pix2),所以我很困惑,爲什麼分組四個像素的大小會改變。我關心這個問題,因爲使用短符號編寫程序比使用2個無符號字符編程更容易,但每像素耗費0.25字節。

我不知道,如果這種體系結構特異性的,因爲我還沒有在其他類型的機器進行測試。它可以對齊嗎?這是我需要擔心的事情,還是我可以繼續執行簡短的實施?

感謝您的幫助提前。

+0

#pragma pack(1)爲了獲得字節對齊的打包(visual studio),那麼你應該在兩種情況下獲得相同的大小。 –

+0

正確的封裝意味着你不關心確切的表示,只關心正在提供的接口。即使內部表示使用兩個單獨的字節,爲'y'取得並返回'uint16_t'也很容易。 –

+0

@Matthieu M .:你說的沒錯。 Getters和setter應該抽象出單個字節的訪問權限,但由於我不熟悉處理相反的endian的差異,所以我很緊張,如果我錯誤地處理了字節序,我會在代碼中引入錯誤。 – Cindeselia

回答

9

的結構的尺寸是相同的,但它們的對準的要求是不同的。

的結構的對準是最大其所有成員的對準的。所以pix1有對齊1,因爲它只有字符,但pix2有從短成員對齊2。 pix4的對齊然後從pixels成員進行對齊,因此第一個爲1,第二個爲2。

現在,以確保數組的所有成員都正確地對準,結構的尺寸被向上舍入到下一個倍數的它的對準。在這兩種情況下,pixels的大小是24,但是接下來是1字節的mask。在第一種情況下,比對是1,所以25是它的倍數,並且sizeof(pix4)是25,但是在第二種中比對是2,所以sizeof(pix4)必須向上取整到下一個偶數,即26. 26.

這是在所有平臺上都一樣。

+0

感謝您的明確解釋。 – fduff

1

同樣的效果是在Linux 32位。

它有填充對準的理由這樣做。

如果你使用struct pix1,你只有字符,因此struct pix4可以保持原樣。但如果您使用struct pix2,它包含一個簡短的內容。因此,整個結構必須對齊,即使在一個數組struct pix4中,每個元素都對齊以便清潔訪問y

更詳細的:一個strict pix4陣列2層的元件將被成形這樣的:

   +-----  [0]  -----+++----- [1]  -----+ 
First version: rgbayyrgbayyrgbayyrgbayyMrgbayyrgbayyrgbayyrgbayyM 
Second version: rgbayyrgbayyrgbayyrgbayyM rgbayyrgbayyrgbayyrgbayyM 
       ---------25--------------+ <- +1 

爲什麼呢?因爲--- ed部分是25個字節,這是一個奇數。第一個版本沒有問題 - 第二個元素可以愉快地從一個奇怪的地址開始 - 但是對於第二個版本。在那裏,yy必須始終在一個偶數(對齊的)地址上,所以struct pix4是26個字節。

+0

「必須始終在一個偶數(對齊)的地址」甚至意味着對齊? –

+0

對齊更多一些:甚至可以被2整除 - 這對於short來說足夠了 - 但在一般情況下(比如int64_t和stuff)甚至是不夠的。 IOW,「對齊」一詞更爲一般。 – glglgl

2

是的,它與對齊有關。編譯器想要對齊natural boundaries上的變量,因此一個短的將是16位(2字節)對齊。因此包含short的結構也將在16位邊界上對齊。

+0

@LuchianGrigore:錯誤,位,而不是字節。自然邊界==類型的大小。 – janneb

+0

我從來沒有聽說過這個詞。介意提供一個參考? –

+0

@LuchianGrigore:對於x86,請參閱http://www.intel.com/Assets/PDF/manual/253665.pdf – janneb