在 c 中,uint8_t structure_member[4] 与 uint32_t structure_member 在结构填充方面有何不同?

In c, how is uint8_t structure_member[4] different than uint32_t structure_member in regards to structure padding?

仅供参考:这是我使用 Whosebug 的第一个问题!

代码如下:

uint8_t TestVar1;
uint8_t TestVar2;


typedef struct
{
  uint8_t member1;
  uint32_t member2;
}Test1;

typedef struct
{
  uint8_t member1;
  uint8_t member2[4];
}Test2;

Test1 TestStruct1; 
Test2 TestStruct2; 

TestVar1 = sizeof(TestStruct1); /*size is 8*/
TestVar2 = sizeof(TestStruct2); /*size is 5*/

我以为我了解填充,但我无法解释 TestVar2。我可以解释 TestVar1 是 8 个字节,因为有 3 个填充字节作为 uint8_t member1.

的一部分

但是,struct test2 没有填充字节吗? (显然不是)有人可以提供一些关于 struct test2 案例中发生的事情的见解吗?

附带说明一下,我的目标是 5 个字节,但我不知道为什么第二种情况有效。数组是否分解为指针或其他东西?这样做安全(标准做法)吗?

谢谢!

uint8_t 没有特定的对齐要求,因此不需要任何填充来对齐它,而 uint32_t 作为多字节类型,需要在 4 字节边界上对齐.如果你绝对必须有一个只占用 5 个字节的 uint8_tuint32_t 的结构,你可以使用 __attribute__((packed)) 告诉编译器放弃填充(我会仔细考虑是否space保存值得错位):

typedef struct __attribute__((packed)) {
    uint8_t member1;
    uint32_t member2;
}test;

另一件需要考虑的事情是结构成员的顺序。要保持减小的结构大小,请将最大的成员放在结构的开头,因为它们将具有最严格的对齐需求。考虑以下因素:

typedef struct {
    uint8_t w;
    uint32_t x;
    uint8_t y;
    uint32_t z;
}test2;

typedef struct {
    uint32_t x;
    uint32_t z;
    uint8_t w;
    uint8_t y;
}test3;

为了保持 uint32_t 成员对齐,test2 将在 wy 之后放置填充,而 test3 已经有 uint32_t 成员对齐并且只在结构的末尾放置足够的填充,以便下一个空闲内存段与 4 字节边界对齐(因为这是任何结构成员的最严格边界)。因此 test2 的大小为 16 字节,而 test3 的大小为 12 字节。

注意:我还没有看到 C 规范中定义的位置(如果有的话),但在我的测试中结果对 gcc 和 clang 都适用。