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

fread读取文件失败及嵌套结构体指针偏移问题求助

问题分析与解决方案

一、一次性读取整个结构体失败的可能原因

从你的代码和描述来看,一次性用fread读取整个outermost_struct失败,最可能的原因是结构体的内存对齐填充。

C编译器为了提升内存访问效率,会自动在结构体成员之间或末尾添加填充字节(padding)。这意味着sizeof(outermost_struct)的实际大小,会比struct_one + struct_two + struct_three的字节总和要大。如果你的二进制文件是按照数据的实际字节数写入的(没有包含这些编译器自动添加的填充字节),那么fread尝试读取的字节数(sizeof(outermost_struct))会大于文件的实际大小,自然会读取失败(返回值小于你指定的读取数量1)。

除此之外,还有几个可能性较低但需要排查的点:

  • 虽然你分读struct_one成功,但如果写入二进制文件时使用的结构体定义和当前代码中的定义不一致(比如子结构体的成员顺序、类型有修改),也可能导致一次性读取失败;
  • 检查fread的返回值,确认是读取失败还是部分读取,这能帮助你进一步定位问题。

二、分结构体读取时如何读取struct_two

首先要纠正一个小细节:你当前读取struct_one的写法fread(&(*settings_mem_location),sizeof(struct_one),1,ptr_file);虽然能成功,但其实更清晰且不易出错的写法是直接指向outermost_struct中的one成员:

fread(&settings_mem_location->one, sizeof(struct_one), 1, ptr_file);

接下来读取struct_two其实很简单:fread执行后会自动移动文件位置指针,它会前进你刚才读取的字节数(也就是sizeof(struct_one)),所以你不需要手动移动指针,直接读取struct_two即可:

fread(&settings_mem_location->two, sizeof(struct_two), 1, ptr_file);

如果因为某些特殊情况(比如中间有其他操作改变了指针位置),需要手动调整文件指针到struct_two的起始位置,可以使用fseek函数:

// 从当前位置前进sizeof(struct_one)字节
fseek(ptr_file, sizeof(struct_one), SEEK_CUR);
// 或者从文件开头定位到struct_one之后的位置
fseek(ptr_file, sizeof(struct_one), SEEK_SET);
// 然后读取struct_two
fread(&settings_mem_location->two, sizeof(struct_two), 1, ptr_file);

注意事项

  • 确保写入二进制文件时的结构体定义和当前代码完全一致(成员顺序、类型、内存对齐设置都要相同),否则分读也会出现数据错乱;
  • 每次调用fread后都要检查返回值,确认是否成功读取了预期的元素数量(这里是1),如果失败可以通过ferror或feof函数判断是文件错误还是到达文件末尾。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:58:18