GCC上32位的结构封装不起作用?

时间:2013-01-14 17:09:36

标签: c++ gcc struct g++ pragma

我在项目中继承了一些第三方代码。它由头文件和没有源代码的二进制库组成,所以我不能用不同的设置重新编译它。

标头使用类似于编译时断言的技巧(如果表达式失败,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来检查它。)

为什么?如何修复代码以使此断言不会失败并使其与ABI保持兼容,同时不必遍历标头中的所有结构并将attribute添加到其尾部?

1 个答案:

答案 0 :(得分:3)

在32位系统上,long long可能不需要八个字节的对齐,四个就足够了。毕竟,你仍然从内存中取出两个完整的单词,无论它们中的第一个是八字节对齐还是四个。

您可以尝试使用属性强制八字节对齐

struct test { char _; long long a __attribute__ ((aligned(8))); };

(可能是错的,我不熟悉gcc的属性)

当然,您还可以向struct添加虚拟成员以确保所需的对齐

struct test { char _; char dummy[7]; long long a; }

这应该在实践中发挥作用。