11

我不确定它是正常的还是编译器错误,但我有一个包含很多成员的 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.

我很难找出为什么我的程序不工作,但我终于发现两者之间有 2 个字节的间隙hlti它被设置为 0x0。这意味着i正在对齐。
当我 printf 结构的那部分时,这一点非常清楚,因为使用:

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

EBF40000EB90EB90在屏幕上。

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

那么是否有 a#pragma或 a__attribute__告诉 gcc 不对齐i内部struct list类型?

4

3 回答 3

36

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

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

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

文档

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

于 2016-11-16T21:42:00.447 回答
7

正如@Banex 所触及

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

内部#pragma pack(push,1)推送当前打包模式,设置packing为1,不填充

#pragma pack(pop) 恢复以前的包装

据说兼容微软的语法

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

于 2016-11-16T22:28:24.287 回答
4

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

话虽如此,字段通常在offest上对齐,该offest是相关数据成员(或数组元素,如果成员是数组)大小的倍数。因此,16 位字段从 2 字节偏移开始,32 位字段从 4 字节偏移开始,依此类推。

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

通过将字段放置在适当的偏移量处,与强制打包struct.

有关详细信息,请参阅这篇关于结构包装的文章。

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

于 2016-11-16T22:04:33.463 回答