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