2017-07-21 79 views
4

我明白填充是如何工作的。我知道路線是什麼。對我來說奇怪的是,爲什麼只有char字段的結構體的大小沒有對齊到4個字節(末尾填充)?我懷疑這只是無法保證的規格,所以編譯器不這樣做。如果是這樣的話,我可以得到這種規則的參考嗎?我最感興趣的是x86和x86-64架構。sizeof c struct只有char字段

實施例:

struct foo { 
    char field1; 
    char field2; 
    char field3; 
} foo2; 

int main(void) 
{ 
    printf("sizeof=%lu\n", sizeof foo2); 
} 

輸出:sizeof=3

+1

你的填充在哪裏?你有3個字符,因此你有3個字節。 – drum

+4

結構不需要在最後填充,因爲大多數系統上的字節('char'是大多數平臺上的8位字節)可以在奇數和偶數地址上訪問,即它們的對齊方式爲'1' 。 –

+1

在ARM OABI(apcs-gnu)中,這將是4字節對齊的。 (不要問我爲什麼,ABI沒有多大意義) –

回答

6

的結構的對準必須使得它的所有字段也正確地對準(特別是如果它們是陣列的一部分)。

由於這裏的所有字段都有一個對齊要求,這也是結構本身的對齊要求。

換句話說,如果您將這些結構中的兩個相鄰放置,則兩個結構中的任何字段都不會違反對齊要求。

對比,與:

struct moreComplexCase { 
    char char1WithAlignment1; 
    // 3 byte gap to align below item. 
    unint32_t uintWithAlignment4; 
    char char2WithAlignment1; 
    // 3 byte gap to align structure itself. 
} 

你會看到兩個填充部分存在。首先是確保uint32_t已正確對齊(您還應該能夠看到結構對齊需要四個,以便uint32_t與給定的填充正確對齊)。

最終填充是爲了確保數組的第二個元素(以及所有後續元素)也將正確對齊。

C標準本身並不指示對齊是什麼,只是該對齊可能存在。例如,早期的x86芯片(可能還有當前的芯片)可以很好地處理未對齊的數據(或者可能會慢一點),而其他架構(例如,早期的ARM芯片)只會在你嘗試這樣做時崩潰或引發故障。

+0

好吧,我想我已經明白了。問題是我認爲在內存地址的本地大小(x86上4個字節和x86-64上8個字節)可分割的地址上訪問此結構會更好。但是,你知道這是否適用於其他架構,如ARM或PowerPC?它是否完全便攜? – hencew5

+0

相當多的CPU支持從任何地址加載單個字節。主要發生的事情是整個緩存行被填滿,所以從此後將字節存入寄存器相對容易。不像Prime機器(古代歷史)那樣,機器上的東西變得有趣。他們有16位字,這是可以加載到寄存器中的最小單位數據。 – bazza

+0

「,而其他架構將像廉價套裝一樣摺疊,如果你試圖這樣做」。這是否意味着未對齊的訪問在這樣的體系結構中不需要太多或任何開銷?我不是母語的人,所以我很困惑在這方面,「摺疊」意味着什麼:) – hencew5