为什么最终指针要与 int 的大小对齐?

Why final pointer is being aligned to size of int?

这是正在考虑的代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

char buffer[512];
int pos;
int posf;
int i;
struct timeval *tv;

int main(int argc, char **argv)
{
    pos = 0;
    for (i = 0; i < 512; i++) buffer[i] = 0;
    for (i = 0; i < 4; i++)
    {
        printf("pos = %d\n", pos);
        *(int *)(buffer + pos + 4) = 0x12345678;
        pos += 9;
    }

    for (i = 0; i < 9 * 4; i++)
    {
        printf(" %02X", (int)(unsigned char)*(buffer + i));
        if ((i % 9) == 8) printf("\n");
    }
    printf("\n");

    // ---  

    pos = 0;
    for (i = 0; i < 512; i++) buffer[i] = 0;
    *(int *)(buffer + 4) = 0x12345678;
    *(int *)(buffer + 9 + 4) = 0x12345678;
    *(int *)(buffer + 18 + 4) = 0x12345678;
    *(int *)(buffer + 27 + 4) = 0x12345678;

    for (i = 0; i < 9 * 4; i++)
    {
        printf(" %02X", (int)(unsigned char)*(buffer + i));
        if ((i % 9) == 8) printf("\n");
    }
    printf("\n");

    return 0;
}

代码的输出是

pos = 0
pos = 9
pos = 18
pos = 27
 00 00 00 00 78 56 34 12 00
 00 00 00 78 56 34 12 00 00
 00 00 78 56 34 12 00 00 00
 00 78 56 34 12 00 00 00 00

 00 00 00 00 78 56 34 12 00
 00 00 00 00 78 56 34 12 00
 00 00 00 00 78 56 34 12 00
 00 00 00 00 78 56 34 12 00

我不明白为什么

*(int *)(buffer + pos + 4) = 0x12345678;

被放入与 int 大小(4 字节)对齐的地址中。我希望在执行此命令期间执行以下操作:

  1. 指向缓冲区的指针,即char*,增加pos的值(0、9、18、27),然后增加4。结果指针为char* 指向 char 数组索引 [pos + 4];
  2. char* 括号中的指针被转换为 int*,导致指针在 base 位置 [=21] 处寻址 4 字节大小的整数=] 和整数数组索引 [0];
  3. 结果 int* 位置以字节 78 56 34 12 的顺序存储(小端系统)。

相反,我看到括号中的指针与 int(4 字节)的大小对齐,但是使用常量的直接寻址(参见第二段代码)按预期正常工作。

更新:感谢Andrew Henle,我现在替换

*(int*)(buffer + pos + 4) = 0x12345678;

        buffer[pos + 4] = value & 0xff;
        buffer[pos + 5] = (value >> 8) & 0xff;
        buffer[pos + 6] = (value >> 16) & 0xff;
        buffer[pos + 7] = (value >> 24) & 0xff;

我不敢相信我必须在 32 位微处理器系统上做这件事,无论它有什么架构,而且 GCC 不能正确地将 int 分割成字节或部分 int 字并对这些部分执行 RMW。

char* pointer in the brackets is being converted to the int*, causing resulting pointer addressing integer of 4 bytes size at base location (buffer + pos + 4) and integer array index [0]

当不满足 int * 的对齐要求时,这会导致 未定义的行为 (UB)。

而是用 memcpy() 复制。一个好的编译器会发出有效的优化代码。

// *(int*)(buffer + pos + 4) = 0x12345678;
memcpy(buffer + pos + 4, &(int){0x12345678}, sizeof (int));