应使用 fread(buf, sizeof(structtype), n, fp),而非 fread(buf, n * sizeof(structtype), 1, fp);前者按元素读取并返回成功个数,后者因 size 过大破坏内部计数,导致读不满、误判或跳过数据。

用 fread 一次性读结构体数组,sizeof 和元素个数别搞反
直接说结论:想高效读 N 个定长结构体,得用 fread(buf, sizeof(StructType), N, fp),不是 fread(buf, N * sizeof(StructType), 1, fp)。后者看似“总字节数对”,但会破坏 fread 的内部计数逻辑,导致读不满、返回值误判甚至跳过后续数据。
常见错误现象:fread 返回值突然变小(比如期望读 100 个,只返回 99),或后续 fread 调用直接读到文件末尾——其实是因为上一次调用因“单次 size 过大”触发了底层缓冲/对齐策略,实际只推进了部分偏移。
- 参数顺序不能颠倒:
size是单个元素大小,count是元素个数,fread按这个语义做循环和错误检查 - 结构体必须是标准布局(POD):不能含虚函数、非公有非静态成员、引用、用户定义构造/析构等,否则
sizeof不代表二进制兼容长度 - 文件必须以二进制模式打开(
"rb"),文本模式在 Windows 下会把\r\n当作一个字符处理,破坏结构体对齐
fread 返回值不是字节数,是成功读入的元素个数
很多人习惯用 if (fread(...) != expected_bytes) 判断失败,这是错的。fread 返回的是成功读取的 count 单位个数,不是字节数。你传的是 sizeof(T) 和 N,它就返回 0~N 之间的整数。
使用场景:批量加载配置表、日志记录、传感器采样点等固定格式二进制数据流。
- 正确判断方式:
size_t n = fread(arr, sizeof(MyStruct), MAX_CNT, fp); if (n -
feof(fp)不能代替错误检查——文件末尾正常结束时fread也返回小于count的值,但ferror(fp)为假 - 若结构体含指针或动态成员,
fread只能读原始内存,后续必须手动修复指针指向(通常不建议这么做)
结构体对齐会影响 sizeof,但不影响 fread 行为本身
fread 不关心对齐,它只是按字节拷贝。但如果你的结构体在 C++ 中因成员排列被编译器插入填充字节,sizeof(MyStruct) 就包含了这些填充——而文件里存的数据也必须按同样对齐规则序列化,否则读出来字段错位。
容易踩的坑:C 头文件里用 #pragma pack(1) 定义结构体,C++ 代码没加对应指令,导致 sizeof 不一致,读出来全乱。
- 跨语言/跨平台时,显式控制对齐:
struct __attribute__((packed)) MyStruct { ... };(GCC/Clang)或#pragma pack(push, 1) ... #pragma pack(pop)(MSVC) - 用
static_assert(std::is_standard_layout_v<mystruct>, "must be POD");</mystruct>在编译期守住底线 - 别依赖
offsetof手动拼接字段读取——性能没优势,还绕过fread的批量优化
附:最小可运行示例(C++17,带错误防护)
#include <cstdio>
#include <cassert><p>struct Record {
int id;
float value;
char tag[4];
};</p>
<p>int main() {
FILE* fp = fopen("data.bin", "rb");
if (!fp) return -1;</p>
<pre class="brush:php;toolbar:false;">constexpr size_t N = 1000;
Record buf[N];
size_t n = fread(buf, sizeof(Record), N, fp);
if (n == 0 && ferror(fp)) {
// 真出错了
perror("fread failed");
}
// 注意:n 是实际读到的 Record 个数,不是字节数
for (size_t i = 0; i <p>}</p>
关键点再强调一遍:结构体定义和二进制文件的内存布局必须严格一致;fread 的 size 参数永远是单个元素大小;返回值是元素个数,不是字节数;所有错误检查都得结合 ferror() 和 feof() 分开判断。
13万字C语言保姆级教程(深入):立即使用
在学习笔记中,你将探索c语言的核心概念和高级技巧!










