我在一个项目中继承了一些第三方代码。它由一个头文件和一个没有源的二进制库组成,所以我不能用不同的设置重新编译它。
标头使用编译时类似断言的技巧(typedef
如果表达式失败,则使用负大小数组)来确保正确的结构对齐,但它似乎不适用于 32 位模式。
这是一个捕获整个问题的独立小程序:
#include <stdio.h>
#include <stddef.h>
#pragma pack(push, 8)
struct test {char _; long long a;};
typedef char pack_test[(offsetof(test, a) == 8) ? 1 : -1];
#pragma pack(pop)
int main(int argc, char *argv[])
{
printf("%d\n", offsetof(test, a));
return 0;
}
上面的代码无法在 clang 3.0 和任何我可以快速上手的最新 gcc 版本(4.5 到 4.7)上编译:打包 pragma 根本没有任何效果。编译器不断将成员对齐a
到 4 个字节(您可以通过注释typedef
out 来检查)。
这是为什么?如何修复代码,以使该断言不会失败并使其与 ABI 兼容,同时不必遍历标头中的所有结构并将attribute
s 附加到它们的尾部?