2012-08-09 54 views
2
typedef struct structc_tag 
{ 
    char  c; 
    double  d; 
    int   s; 
} structc_t; 

我在博客中讀取,這將取數據的24個字節:混亂在結構成員對齊

的sizeof(char)的+ 7字節的填充+的sizeof(雙)+的sizeof(int)的+ 4字節填充= 1 + 7 + 8 + 4 + 4 = 24字節。

我的問題是爲什麼7字節的填充,爲什麼我們不能在那裏使用3字節的填充,並利用接下來的8字節來加倍?最後4個字節需要什麼?

+1

'double'實體應該對齊到可被8整除的地址,否則當試圖從內存加載值時,FPU可能會變得不快樂。在這種情況下,必須發出非常慢的未對齊負載(並且某些平臺根本不支持未對齊的訪問)。在x64 CPU上的64位模式下尤其如此,其中數學主要使用SSE完成。最後四個字節用於保證在堆疊多個這樣的結構時(例如,在一個'struct_t'數組中),正確對齊。 – 2012-08-09 17:41:21

+1

通常很難確切知道實際實現中結構或對象的大小,因爲它在您使用的每個平臺上都會發生變化。您通常只需依靠編譯器盡其所能地完成必要的字段和填充以獲得最佳性能。這就是爲什麼人們在檢查對象使用的字節數時使用'sizeof()'的原因 - 即使是像int這樣的基本類型。 – Pyrce 2012-08-09 17:43:17

+0

如果你願意,只需根據它們的大小對字段進行排序,就你的情況而言,這可能對大多數平臺有所幫助 – 2012-08-09 18:25:57

回答

3

你需要考慮,如果你分配這些結構的陣列malloc()了,會發生什麼:

structc_t *p = malloc(2 * sizeof *p); 

考慮一個平臺,讓sizeof(double) == 8sizeof(int) == 4和所需的double對齊8 malloc()總是返回地址正確對齊用於存儲任何C類型 - 因此在這種情況下,a將被8字節對齊。填充要求然後自然脫落:

  • 爲了a[0].d爲8字節對齊,因此必須有7個字節的填充a[0].c後;

  • 爲了使a[1].d爲8字節對齊,整個結構尺寸必須是8的倍數,因此在a[0].s之後必須有4個字節的填充。

如果重新排序struct從最大到最小:

typedef struct structc_tag 
{ 
    double  d; 
    int   s; 
    char  c; 
} structc_t; 

...那麼唯一需要的填充是.c後3個字節,使結構尺寸8的倍數。這導致結構的總大小爲16,而不是24.

2

它取決於平臺,但它取決於double與哪個對齊。如果它對齊到8個字節,看起來是這種情況,3個字節的填充不會將其剪切。

如果double被對齊到4個字節,你會是正確的,將使用3個字節的填充。

+0

對於OP,有時可以通過使用雜注來覆蓋默認對齊選項。例如對於gcc,使用#pragma pack(1)來使用1字節對齊,#pragma pack(4)等等。你必須看看你的編譯器支持什麼。請注意,未對齊的內存訪問速度可能會比浪費空間慢得多,並讓編譯器使用目標機器的首選對齊方式。 – 2012-08-09 17:53:52