簡體   English   中英

GCC 上的 #pragma pack(push, n)/#pragma pack(pop) 和 __attribute__((__packed__,aligned(n))) 之間有什么區別?

[英]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.

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