【发布时间】:2019-07-22 04:58:40
【问题描述】:
有时我们有一个 POD 结构,其 sizeof 具有序列化目的的含义。来自我的 PE 解析器,来自示例:
struct dos_header {
unsigned short magic;
unsigned short cblp;
...
};
这个结构是为了从/到 PE 图像序列化,所以它上面的sizeof 有一个含义,比如ifstream::read。
这当然对非 POD 无效。以 nt_header 为例:
struct nt_header
{
std::uint32_t Signature;
file_header FileHeader;
std::variant<optional_header_32, optional_header_64> OptionalHeader;
}
使用sizeof 进行序列化在技术上是有效的,但在运行时是无稽之谈,因为结构的大小取决于运行时。
在这样的类中使用sizeof时,有没有办法强制编译器产生编译时错误?
所以,如果我不小心在某处使用了sizeof(nt_header),编译器会警告我。
【问题讨论】:
-
来自C++ FAQ:sizeof 不能重载,因为内置操作,例如将指针递增到数组中隐式依赖于它。 而 sizeof()它具有序列化目的的含义这不是唯一的目的。因此,对预期的 POD 类型没有限制。 (可能是,可以使用基于 clang 的扩展工具来检测这一点,但我担心
std标头中的误报。) -
顺便说一句。基于
sizeof的序列化听起来像是转储二进制数据而忽略字节序。这不是可移植的(但我猜你已经意识到它并忽略它以获得额外的性能)。 -
这是一个 XY 问题,您尝试在使用
sizeof时触发错误,从而导致错误的树出现。您需要做的就是根据对象是否为标准布局类型来专门读取或写入对象的函数。这可以使用std::is_standard_layout()(C++11 及更高版本)来实现。可以在二进制流上使用ifstream::read()安全地读取标准布局类型(假设由使用兼容编译器构建的程序编写),而其他类型则不能。 -
运营商是
sizeof,而不是sizeof()。程序员经常添加多余的括号,但它们仍然是多余的。您不应该使用struct作为序列化协议。出错的方式还有六种以上。 -
@MichaelChourdakis 我这样做了,我做到了,而且我首先做到了,实际上,但我不接受“代替”。即使对您个人而言,解释也有价值