如何告诉 gcc 禁用结构内的填充?

How to tell gcc to disable padding inside struct?

我不确定这是正常现象还是编译器错误,但我有一个包含很多成员的 C 结构。其中,有:

struct list {
    ...  
    ...
    const unsigned char nop=0x90; // 27 bytes since the begining of the structure
    const unsigned char jump=0xeb; // 28 bytes since the begining of the structure
    const unsigned char hlt=0xf4; // 29 bytes since the begining of the structure
    unsigned __int128 i=0xeb90eb90eb90eb90f4f4 // should start at the 30th byte, but get aligned on a 16 byte boundary and starts on the 32th byte instead
    const unsigned char data=0x66; // should start at the 46th byte, but start on the 48th instead.
}; // end of struct list.

我费了好大劲才弄明白为什么我的程序不工作,但我终于发现hlti[=33之间有2个字节的差距=] 设置为 0x0。这意味着 i 正在对齐。
当我打印那部分结构时,这是非常清楚的,因为 with :

for(int i=28;i<35;i++)
    printf("%02hhX",buf[i]);

我在屏幕上显示 EBF40000EB90EB90

我在我的程序中尝试了volatile struct list data;之类的东西,但它并没有改变对齐问题。

那么是否有 #pragma__attribute__ 告诉 gcc 在 struct listtype 中不对齐 i

在 GCC 中,您可以像这样使用 __attribute__((packed))

// sizeof(x) == 8
struct x
{
    char x;
    int a;
};

// sizeof(y) == 5
struct y
{
    char x;
    int a;
} __attribute__((packed));

doc

此外,如果您依赖结构字段的地址,请查看 offsetof 宏。也许你根本不需要打包结构。

struct 中的字段以实现定义的方式填充。

话虽这么说,字段通常按偏移量对齐,偏移量是相关数据成员(如果成员是数组,则为数组元素)大小的倍数。因此,16 位字段从 2 字节偏移量开始,32 位字段从 4 字节偏移量开始,依此类推。

如果您对 struct 中的字段重新排序以遵守此准则,通常可以避免在 struct 中使用任何内部填充(尽管您最终可能会有一些尾随填充)。

通过将字段置于适当的偏移量,可以比强制打包 struct.

提高性能

有关详细信息,请参阅 this article on structure packing

虽然不能保证使用上述技术,但它们往往在大多数情况下都有效。

如@Banex 所述

#pragma pack(push,1)
struct
{
        char a;
        int b;
        long long c;
} foo;
#pragma pack(pop)

#pragma pack(push,1)内推当前的packing模式,packing设置为1,无padding

#pragma pack(pop)恢复之前的打包

据称与 Microsoft 的语法兼容

http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html