2013-01-07 208 views
7
#include <stdint.h> 
#include <stdio.h> 

typedef union { 
    uint64_t u[2]; 
    struct { 
     uint64_t a:30; 
     uint64_t b:30; 
     uint64_t c:30; 
     uint64_t d:30; 
     uint64_t e:8; 
    }x; 
} mystruct; 

int main() 
{ 
    printf("Size %d\n", sizeof(mystruct)); 
} 

我想在64位機器上編譯它。預期的輸出是16,但我越來越24. 我知道一些對齊發生在這裏,但我不知道爲什麼,因爲結構x是正好16個字節。 有人可以解釋這一點。 感謝sizeof沒有顯示預期的輸出

+2

您正在使用位字段:K&R第150頁:*」幾乎所有關於位域的東西都是依賴於實現的「*」。我個人會忽略「幾乎」。 – cdarke

+2

@cd他們說*幾乎*因爲其餘未指定;) – ouah

回答

6

從C標準:

(C99,6.7.2.1p10)「[...]如果沒有足夠的空間仍然存在, 是否不適合一個位域放入下一個單元或重疊的相鄰單元是 實現定義的。「

因此,在你執行不重疊:ab成員都在一個單元,cd在另一個單元和e是另一個單位:8 + 8 + 8 = 24

6

對於64位機,字段ab使用在結構中的第一個64位值的60個比特,cd使用在結構中的下一個64位值的60位值,並將因爲e是8位,它不適合從該64位值剩餘的4位,因此需要另一個64位值。因此8×3 = 24個字節。

3

位字段的元素將永遠不會重疊兩個內存單元(在您的情況下內存單元是64位元素)。

旁邊的事實是位域的實現都依賴於編譯器,還有就是你的位域的結構實際上是存儲在內存中通過以下方式一切機會:

struct { 
    uint64_t a:30; 
    uint64_t b:30; 
    uint64_t :4; 
    uint64_t c:30; 
    uint64_t d:30; 
    uint64_t :4; 
    uint64_t e:8; 
    uint64_t :56; 
}x;