仅POD类型结构体可安全用reinterpret_cast写文件;含指针、string、vector或虚函数的非POD类型会因野指针或无效数据导致崩溃。
直接用
强转结构体指针写文件,多数情况会出错
结构体里只要含指针、
、
或虚函数表(比如有虚函数),就不能简单把整个对象地址 reinterpret_cast 成
写进文件。因为这些成员存的是运行时堆地址或内部动态数据,序列化后读出来只会得到野指针或无效长度,运行时大概率崩溃。
真正能安全强转的,仅限于「POD 类型」:纯 C 风格结构体,所有成员都是内置类型(
、
、
等),无构造函数、析构函数、虚函数、非静态成员函数、访问控制符(
/
)——且编译器没加 padding 干扰(需确认内存布局)。
检查是否 POD:
(C++17 起已弃用但仍可用),更推荐
+
强制对齐避免 padding:
或
,但注意跨平台读写时
字节
序和对齐差异
写入前务必用
校验大小,别信结构体声明看起来多“紧凑”
用
写二进制,必须配合
标志
漏掉
是 Windows 下最常见翻车点:文本模式会把
自动转成
,导致读取时字节偏移全乱,结构体字段错位。Linux/macOS 虽不转换换行符,但显式指定 binary 更安全、语义更清晰。
正确打开方式:
写结构体(仅限 trivially copyable):
写多个连续结构体(如数组):
写完记得
或作用域结束自动析构,否则缓冲区可能未刷盘
读取时不能只靠
,还要校验长度与 EOF
用
读二进制,返回值是流对象本身,不能直接判断成功与否;实际要查
返回值是否等于预期字节数,否则可能只读了一半就遇到文件尾或 I/O 错误。
C函数速查手册(CHM版)
C函数速查手册(CHM版)
下载
立即学习
“
C++免费学习笔记(深入)
”;
读单个结构体示例:
读数组时循环内每次都要检查
,别假设
一定能读满
结构体含固定长度数组(如
)时,读出后建议用
截断,避免后续当 C 字符串用时越界
跨平台序列化必须处理字节序(Endianness)
x86/x64 默认小端,ARM 可能大端,网络协议常用大端。如果文件要在不同架构机器间交换,整数字段(
、
等)必须统一字节序,否则读出来数值完全错误。
写入前转网络字节序:
(16 位)、
(32 位)、
(POSIX)或手动移位
读取后转主机字节序:
、
、
浮点数没有标准字节序转换函数,需按整数 reinterpret_cast 后再转,或改用文本/Protocol Buffers 等方案
结构体中混用大小端字段极难维护,建议整个文件统一约定(如全用大端),并在文件头加 magic number 和版本标识
结构体序列化的坑不在语法,而在内存模型、I/O 行为和平台差异的叠加。哪怕一个
成员没手动序列化,或一次
检查被跳过,都可能让程序在某个环境静默失败。
reinterpret_caststd::stringstd::vectorchar*intdoublechar[16]privateprotectedstd::is_pod_vstd::is_trivially_copyable_vstd::is_standard_layout_v#pragma pack(1)alignas(1)sizeof(MyStruct)std::ofstream.write()ios::binaryios::binary\n\r\nstd::ofstream file("data.bin", std::ios::binary);file.write(reinterpret_cast(&s), sizeof(s)); file.write(reinterpret_cast(arr), sizeof(MyStruct) * count); file.close()read()std::ifstream.read()gcount()MyStruct s;
in.read(reinterpret_cast(&s), sizeof(s));
if (in.gcount() != sizeof(s)) {
// 读取失败:文件损坏、提前 EOF 或权限问题
} gcount()read()char name[32]strnlenint32_tuint64_thtons()htonl()htobe64()ntohs()ntohl()be64toh()std::stringgcount()