为什么一个字符只有 1 个填充字节(在 32 位机器上)?

Why is there only 1 padding byte for a char (on a 32-bit machine)?

A tutorial on data padding 表示下面 C 结构中 int i 后面的 char c 需要 1 个填充字节。

struct test2
{
    int i;
    // 4 bytes
    char c;
    // 1 byte
    // 1 padding byte. <-- question here
    short s;
    // 2 bytes
};

考虑到在这种情况下内存访问是 32 位的,我想了解为什么不是 3 字节填充?

每个成员的对齐方式才是最重要的。考虑每种类型的对齐要求。对于 int,在您的情况下,它是 4 字节。一个char,自然是1short 怎么样?那么在您的体系结构上,它似乎是 2 字节。我们希望每个成员都根据自己的对齐要求对齐。

因为 int 是第一个成员,我们不需要任何填充(但这确实会影响 struct 的整体大小)。然后,我们有一个char,它的要求最宽松,所以我们不需要为它填充。然后是short。它需要对齐到 2 个字节。我们目前处于 5 个字节的偏移量,因此我们需要一个填充字节来使 short 正确对齐。总而言之,这给了我们 8 个字节,并且也符合整个结构的对齐方式,所以最后不需要额外的填充。

一般来说,结构的最小尺寸将通过从最强对齐要求到最弱排列成员来实现。这不一定是获得最小尺寸的唯一顺序,但可以保证没有其他顺序会更小。

来自Unaligned Memory Accesses

Unaligned memory accesses occur when you try to read N bytes of data starting from an address that is not evenly divisible by N (i.e. addr % N != 0). For example, reading 4 bytes of data from address 0x10004 is fine, but reading 4 bytes of data from address 0x10005 would be an unaligned memory access.

int大小为4字节,short大小为2字节,char大小为1字节(64位系统)。

假设起始地址为 0x0000。
所以,int i占用0x0000到0x0003。
char c 存储在 0x0004(因为地址可以被 1 整除)。

假设char c后没有1字节填充,那么short s会被存放在0x0005处,不能被2整除,这会导致内存访问不对齐

为了防止这种情况,我们在 char c 之后添加了 1 个字节的填充。填充1个字节后,short s将被存储为0x0006,被2整除。