簡體   English   中英

填充和對齊-誤解

[英]Padding & Alignment - misunderstanding

給出以下非常簡單的結構:

struct A {

    int a;
    double b;

};

(使用Mac OS 10.9-Xcode)

結構的大小為16。我不明白為什么。 為什么不是12? 12是4的倍數。

謝謝

編輯:

struct B {

int a;
char b[4];
char c[4];
};

該結構的大小為12。因此,這意味着它是合格的大小。 為什么編譯器然后用另外4個字節填充第一個結構?

編譯器和體系結構可能更喜歡double b的地址在8字節邊界上對齊,因為sizeof(double) == 8 ,就像它更喜歡int a的地址在4字節邊界上對齊一樣。

因此,編譯器可能會在“ int a”和“ double b”之間插入4個字節的“ padding”,以使兩個變量都可以在預期的邊界上對齊。

大多數編譯器通常提供一種關閉填充的方法(對網絡/磁盤序列化很有用),但這取決於編譯器。 在Windows上是#pragma pack(1) 在gcc上,它是__attribute__ ((packed))不確定Mac / Clang是否具有類似的屬性。

4不是一個神奇的數字。 通常根據標量對象的大小進行對齊,在這種情況下, double值為8。 但這不是硬性規定。 機器或平台可以決定所需的對齊要求。

請參閱ABI規范以獲取完整的(閱讀:精打細算)詳細信息。

編譯器需要添加填充以確保結構的每個成員的地址都應根據其類型對齊。

在這種情況下:

struct A {
    int a;
    double b;

};

假設sizeof(int)是4, sizeof(double)是8,則地址a應該是4的倍數,地址b 8的倍數(這就是所謂的自然對齊。)如果基地址如果此類型的變量為零,則為了使該變量的成員b的地址滿足其對齊要求,編譯器需要在成員a之后添加一個4字節的填充。

在第一種情況下添加了填充,因為在您的計算機上, double精度字對齊為8個字節。 因此,它必須位於可被8整除的地址處。

0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 

a    a    a    a    |     padding     | b    b    b    b    b    b    b    b

如果未添加填充,則double成員將從地址0x04開始,這是錯誤的。 加上4個填充字節。 現在, double 0x080x08 因此,大小為16。

對於第二種情況:

struct B {

 int a;
 char b[4];
 char c[4];
};

0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 
a    a    a    a    b[0] b[1] b[2] b[3] c[0] c[1] c[2] c[3]

在這種情況下,如果基址再次為0,則不需要填充,因為所有對齊。

嘗試這個 :

struct B {
 char b[5];
 int a;
 char c[4];
};

大小為16個字節。 添加了填充,以便int成員的起始地址為可被4整除的地址。

0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F
b[0] b[1] b[2] b[3] b[4] |   padding  | a    a    a    a    c[0] c[1] c[2] c[3]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM