【问题标题】:What is happening when a user-defined type is cast to a char*?将用户定义的类型强制转换为 char* 时会发生什么?
【发布时间】:2016-12-03 03:28:29
【问题描述】:

我遇到了一个课程,我们使用了一个名为“Person”的用户定义类型,它将一个人的姓名存储在一个 char 数组中,并将年龄存储为一个整数。课程是关于写入和读取二进制文件的。主程序如下所示:

int main()
{
Person anil("anil",24); //initialize with name and age

fstream file("person.bin", ios::binary | ios::in | ios::out | ios::trunc);

if (!file.is_open())
    cout << "Error while opening file.";
else
{
    file.write((char*)&anil, sizeof(Person));
    file.seekg(0); // go back to beginning

    Person anjali;  //declare new person object

    //first argument is memory block, second argument is byte size
    file.read((char*)&anjali, sizeof(Person));

    anil.whoAreYou();  //outputs the name and age
    anjali.whoAreYou();
}

return 0;
}

我不明白这些行发生了什么:

file.write((char*)&anil, sizeof(Person));
file.read((char*)&anjali, sizeof(Person));

我知道 fstream 的写入和读取功能需要 memory_block 作为第一个参数...有人可以解释当对用户定义类型的引用转换为 char * 时到底发生了什么?

【问题讨论】:

  • 将内存转储到磁盘并认为以后有希望工作可能是个坏主意。这可能包含指针或结构,如std::string,将数据存储在其他地方。尝试编写一个正确的序列化方法为operator&lt;&lt;,这样你就可以做到file &lt;&lt; anil
  • 课程是关于写入和读取二进制文件的。 -- 啊哈!这个糟糕的“教训”在哪里教?我问这个,因为这里必须有成千上万的帖子,发帖人写的代码完全像这样,并且无法理解为什么他们的程序不起作用。我推测有人、某本书或某个网站正在将这些信息提供给新手 C++ 编码人员。
  • 我觉得这是不好的做法。

标签: c++ binaryfiles file-writing file-read


【解决方案1】:

在 C/C++ 中,char * 通常用作通用类型的数据,因为它始终指向 1 个字节。代码中的转换代码(char*)&amp;anil 使用&amp; 获取指向anil 的指针,并将其转换为指向chars 的指针。它将chars 的序列写入文件,然后将其读回到anjali 的内存中。

这会执行精确的内存复制,如果您有指向该内存中其他位置的指针,则会导致问题,因为该指针在加载对象时几乎永远不会有效。这可以作为一个例子,但现实世界的序列化非常棘手,通常最好留给某种序列化库。手动序列化是可能的,但只能在图书馆等中非常小心地完成。

如果您希望进行这种手动序列化,您需要确定序列化的格式并将基值写入文件。您还需要确定您是否真的需要二进制序列化,或者基于文本的序列化是否更适合。在大多数情况下,将对象写入 JSON 等文件格式会更容易一些,并且还具有可在语言之间移植和人类可读的优势。

【讨论】:

  • 我不知道转换到和返回文件,特别是从用不同编译器编译的不同平台,是否会导致对齐问题。至少,执行static_cast
  • 是的,肯定是这样。我什至没有考虑不同编译器可能出现的对齐/排序问题。我想即使在具有相同编译器的同一台机器上,也可能基于编译选项发生此类问题。但是一味地投到char * 写的方法,反正最简单的情况下也有可能出问题。
【解决方案2】:

std::fstream 派生自 std::istream 基本上是 basic_istream&lt;T&gt;char as T 的 typedef。

所以,fstream::read 需要一个 char 指针作为第一个参数,并且强制转换将 anil 的起始地址转换为 char*。因为在大多数系统上,sizeof(char) == 1 必须复制个人实例逐个字节到提供的地址。

从长远来看,这既不可移植也不可维护,特别是如果您在类中将指针作为成员变量,因为您实际上会序列化变量的原始内存地址。

【讨论】:

    猜你喜欢
    • 2021-05-07
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 2015-12-19
    • 2012-06-12
    • 1970-01-01
    • 2015-03-13
    相关资源
    最近更新 更多