2014-09-13 21 views
10

我正在linux上使用c中的結構。 我開始使用位字段和「壓縮」屬性,我碰到一個奇怪的行爲傳來:c結構中的壓縮位字段 - GCC

struct t1 
{ 
    int a:12; 
    int b:32; 
    int c:4; 
}__attribute__((packed)); 

struct t2 
{ 
    int a:12; 
    int b; 
    int c:4; 
}__attribute__((packed)); 

void main() 
{ 
    printf("%d\n",sizeof(t1)); //output - 6 
    printf("%d\n",sizeof(t2)); //output - 7 
} 

怎麼來的這兩個結構 - 這是完全一樣的 - 採取的字節數不同勢?

+1

因爲't2 :: b'保證是一個不同的內存位置?想想數據競賽。 – 2014-09-13 11:26:00

回答

10
struct t1 // 6 bytes 
{ 
    int a:12; // 0:11 
    int b:32; // 12:43 
    int c:4; // 44:47 
}__attribute__((packed)); 

struct t1 // 7 bytes 
{ 
    int a:12; // 0:11 
    int b; // 16:47 
    int c:4; // 48:51 
}__attribute__((packed)); 

常規的int b必須與字節邊界對齊。所以在它之前有填充。如果您將c置於a的旁邊,則不再需要此填充。您應該這樣做,因爲訪問像int b:32這樣的非字節對齊整數很慢。

16

你的結構不是「完全一樣」。你的第一個有三個連續的比特字段,第二個有一個比特字段,一個(非比特字段)int,然後是第二個比特字段。

這是有意義的:連續(非零寬度)位字段合併成一個單獨的存儲位置,而位字段後跟非位字段是不同的存儲位置。

您的第一個結構有一個內存位置,第二個結構有三個。您可以在第二個結構中獲取b成員的地址,而不是第一個。訪問b成員不會在第二個結構中訪問ac,但它們會在第一個結構中進行。

緊接在位字段成員「關閉」它的一個sens之後有一個非位字段(或一個零長度位字段),接下來將是一個不同的/獨立的內存位置/對象。編譯器不能像在第一個結構中那樣將您的b成員「打包」在位字段內。