You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何fwrite写入uint8_t相关结构体时产生4字节而非预期3字节?

为什么结构体写入文件多了1字节?

哈哈,这个坑我当年刚学C的时候也踩过!问题出在**结构体的内存对齐(padding)**上,编译器为了让CPU更高效地访问数据,会自动在结构体成员之间或者末尾添加填充字节,这就是你看到多出来那个00的原因。

具体分析你的代码:

你定义的结构体:

struct a {
    uint8_t x;  // 占1字节
    uint16_t y; // 占2字节
};

uint16_t类型的数据要求对齐到2字节的内存边界(因为它的大小是2字节),所以编译器会在x后面补1个字节的填充,让y的起始地址是2的倍数。这样整个结构体的大小就变成了1+1+2=4字节,而不是你预期的3字节。

这就是为什么fwrite(&record, sizeof(struct a), 1, fp)会写入4字节,对应hexdump里的01 00 02 00:

  • 01是x的值
  • 00是编译器自动添加的填充字节
  • 02 00是y的值(因为你的系统是小端字节序,uint16_t的2会被存储为低字节在前)

解决方法

方法1:让结构体“紧凑”排列(取消自动对齐)

使用编译器特定的属性来告诉编译器不要添加填充字节。比如GCC/clang可以用__attribute__((packed)):

struct a {
    uint8_t x;
    uint16_t y;
} __attribute__((packed));

修改后sizeof(struct a)就是3字节,写入文件后就会得到你预期的01 02 00。

⚠️ 注意:这种方式可能会导致CPU访问非对齐数据时性能下降,甚至在一些严格要求对齐的架构(比如部分ARM设备)上触发错误,但对于写入二进制文件这种需要严格控制字节布局的场景,完全可以用。

方法2:手动打包数据写入

如果你不想修改结构体的对齐属性,可以手动把成员数据打包成字节数组再写入:

uint8_t data[3] = {
    record.x,
    (record.y >> 8) & 0xFF,  // y的高字节
    record.y & 0xFF          // y的低字节
};
fwrite(data, sizeof(data), 1, fp);

这样也能精确控制写入的字节序列,避免对齐带来的问题。

内容的提问来源于stack exchange,提问作者raupach

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:36:51