紧凑结构体的最后对齐方式

3

有没有办法让gcc仅在紧凑结构的末尾进行填充?

我正在使用紧凑结构进行空间优化,但也将该结构用于计算内存偏移量(在缓冲区中存储多个结构)。因此,如果我的结构的总大小未对齐(不是4的倍数),如果我尝试访问缓冲区中的下一个结构,我将收到SIGBUS信号。

例如:

sizeof(my_packed_struct) == 11
sizeof(other_struct) == 12

如果我将my_packed_struct放在地址0x2000处,那么我也会将other_struct放在0x200B(+11字节)处。
因此,如果我想访问other_struct,例如(other_struct*)0x200B,我会收到SIGBUS信号。
所以我很好奇是否有一种方法可以使GCC填充结构以避免这个问题。
以下是定义:
typedef struct __attribute__ ((packed)) my_packed_struct {
    uint8_t att1;
    bool att2;
    uint32_t att3;
    uint32_t att4;
    bool att5;
} my_packed_struct;

我可以像这样添加一个属性

typedef struct __attribute__ ((packed)) my_packed_struct {
    uint8_t att1;
    bool att2;
    uint32_t att3;
    uint32_t att4;
    bool att5;
    uint8_t pad;
} my_packed_struct;

为了确保匹配到大小12,但我正在寻找一种解决方案,不需要手动计算大小和填充(例如,如果将来必须添加另一个属性)。
我看了gcc结构体中的内存对齐,我确实在内部缓冲区中存储结构体,但我仍然需要暴露一个结构体以方便客户端使用。

为了进行空间优化,首先不要使用bool。并且将bool和char字段放在相邻的位置,这样它们只需要对齐一次。 - wildplasser
我假设这是针对嵌入式系统的,否则即使您创建数百万个结构体,也不必保存仅几个字节。至于您的问题,other_struct是否必须直接跟在紧凑结构体后面?为什么不将其放置在紧凑结构体之后一个良好对齐的地址上?然后填充将是两个结构体之间的空白空间。 - Some programmer dude
哦,还有一件事,你可能把other_structure放在0x200B,对吧?否则就会重叠了。 - Some programmer dude
手动添加填充吗? - Jonathan Leffler
@Someprogrammerdude 是的,这是为嵌入式系统设计的,并且你说得对,它是0x200B。other_struct必须遵循其他结构(基本上是头部/有效载荷)。此外,我不想让编写者负责对齐结构。 - joetde
可能是内存对齐问题的重复。 - Alex
1个回答

1
这个技巧怎么样?
union __attribute__ ((packed)) struct_union
{
    struct my_packed_struct data;
    int pad[(sizeof(my_packed_struct)+3)/sizeof(int)];
} struct_union;

并且使用struct_union代替直接使用my_packed_struct?

为什么会奏效?

  1. 联合体是紧密排列的,因此不会额外填充
  2. 填充始终是4的倍数(由于int)
  3. sizeof计算将确保它足够大以容纳整个my_packed_struct

你应该将3替换为sizeof(int)-1(或者源代码中的任何数字)。 - M.M
是的 - 3等于sizeof(int)-1。int也可以被其他类型替换 - 但问题是关于4字节对齐的。 - Anty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接