繁体   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