为何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
相关产品推荐
相关产品推荐

