我正在用C ++编写一个记录器,我来到了我想要记录日志并写入文件的部分。
我创建了一个LogRecord
结构,并希望将其序列化并以二进制模式将其写入文件。
我已经阅读了一些关于C ++序列化的帖子,其中一个答案包括以下代码片段:
reinterpret_cast<char*>(&logRec)
我试过阅读有关reinterpret_cast
及其作用的内容,但我无法完全理解后台发生的事情。
根据我的理解,它需要一个指向我的struct的指针,并将其转换为指向char的指针,因此它认为保存我的struct的内存块实际上是一个字符串,是真的吗?这怎么办?
答案 0 :(得分:9)
内存地址只是一个内存地址。内存本身并不特殊 - 它只是一个庞大的字节数组,对于我们所关心的所有内容。赋予记忆意义的是我们用它做的事情,以及我们通过它观察它的镜头。
指向struct的指针只是一个整数,它指定了一些内存的偏移量 - 当然,你可以以任何你想要的方式处理一个整数,作为指向某个任意字节数的指针(char
或多个)。
reinterpret_cast()
没有做任何特殊操作。您仍然可以正确处理该内存地址。
例如,char*
是在C ++中引用字符串的传统方式 - 但类型char*
字面意思是“指向单个字符的指针”。它是如何表示指向以null结尾的字符串的指针?按惯例,就是这样。我们根据具体情况对这种类型进行不同的处理,但我们应该确保这样做是正确的。
例如,您如何知道通过指向结构的char*
指针读取多少字节?类型本身为您提供零信息 - 由您自己知道您确实有一个指向固定长度结构的面向字节的指针。
请记住,在引擎盖下,机器没有类型。如果你在每一行写一篇文章,或者如果你乱涂乱画,那么一张纸并不在乎。这就是我们对待它的方式 - 以及我们使用的工具(C ++)如何对待它。
答案 1 :(得分:3)
二进制,它什么都不做。这种铸造是一种更高级别的概念,与任何实际的机器指令无关。
在低级别,指针只是一个包含内存地址的数值。告诉编译器没什么可做的,虽然您认为目标内存包含struct
,但现在请认为它包含char
&#34;。实际地址本身并没有任何改变。
答案 2 :(得分:1)
根据我的理解,它需要一个指向我的struct的指针,并将其转换为指向char的指针,因此它认为保存我的struct的内存块实际上是一个字符串,是真的吗?
是
这怎么办?
一个字符串只是一个字节序列,你的对象只是一个字节序列,所以它是如何工作的。
但如果您的对象逻辑不仅仅是一个字节序列,它赢了。任何间接,你都被冲洗了。此外,任何实现定义的填充或表示/字节顺序和您的数据都是不可移植的。这可能是可以接受的;这实际上取决于你的要求。
答案 3 :(得分:0)
将结构体转换为字节数组(字符串)是二进制序列化的经典低影响方法。这是基于结构内容在内存中连续存在的假设。转换允许我们使用普通API将此数据写入文件或套接字。
仅当数据是连续的时才有效。对于C ++术语中的C样式结构或POD,这是正确的。它不适用于复杂的C ++对象或任何带有指向结构外部存储的指针的结构。对于文本数据,您需要使用固定大小的字符数组。
struct {
int num;
char name[50];
};
将正确序列化。
struct {
int num;
char* name;
};
将无法正确序列化,因为字符串的数据存储在struct之外;
如果要通过nework发送数据,还需要确保结构已打包或至少已知对齐,并且整数转换为一致的字节顺序(网络字节顺序通常为大端)