[英]what is the difference between __attribute__((__packed__)); and #pragma pack(1)
[英]What are the differences between #pragma pack(push, n)/#pragma pack(pop) and __attribute__((__packed__, aligned(n) )) on GCC?
具體在 GCC 上(即兩者都用 GCC 編譯),以下兩者的工作方式有什么區別?
struct foo1 {
char a;
int b;
} __attribute__((__packed__, aligned(n) ));
和:
#pragma pack(push, n)
struct foo2 {
char a;
int b;
};
#pragma pack(pop)
他們的行為似乎不同:
foo1 f1;
foo2 f2;
int& i1 = f1.b; // ok
int& i2 = f2.b; // cannot bind packed field 'f2.foo2::b' to 'int&'
為什么一個有錯誤而另一個沒有? 至少內存布局是一樣的嗎?
您沒有說明您使用的是哪個版本的 GCC,但您可以在網上找到相應的手冊。 它們在這些方面都非常兼容,但是,因為屬性和編譯指示的行為一旦定義,通常會跨版本維護以實現兼容性。 我將從 GCC 4.9.3 的手冊中引用具體的引文,GCC 4.9.3 目前是 GCC 4 系列的最新可用版本。 特別是,有關類型屬性和結構包裝 pragma 的部分是相關的。
GCC 手冊提到#pragma pack
和朋友:
#pragma 指令更改隨后定義的結構(零寬度位域除外)、聯合和類成員的最大對齊方式。
(強調)。 它說__attribute__((packed))
:
此屬性附加到結構或聯合類型定義,指定結構或聯合的每個成員(零寬度位字段除外)的放置以最小化所需的內存。
它說__attribute__ ((aligned(n)))
:
此屬性指定指定類型的變量的最小對齊方式,以字節為單位。
(強調)。
因此,不, #pragma pack(n)
,無論是否帶有push
,通常與將__attribute__((packed, aligned(n))
附加到結構類型的含義不同。前者指定受影響結構的成員在n
字節或更精細的邊界上對齊。后者指定受影響結構的成員用最小的允許填充填充,並且整個結構實例的所選對齊要求必須不小於n
。不僅是那些不一樣,它們甚至不是很相似。
您應該發現影響結構定義的#pragma pack(1)
對實例布局的影響與將__attribute__((packed))
附加到該結構的定義相同。 然而,即使他們達到了同樣的目的,他們也不是一回事。 兩者的行為和效果都在 C++ 規范之外,GCC 完全有權在其他方面區別對待它們。
但是,如果要使用屬性來影響結構成員的對齊方式,則至少需要逐個成員地應用一些屬性。 例如 ...
struct foo1 {
char a;
int b __attribute__((aligned(n)));
} __attribute__((packed));
... 可能與 ... 具有相同的效果
#pragma pack(push, n)
struct foo2 {
char a;
int b;
};
#pragma pack(pop)
...,取決於n
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.