【问题标题】:Why does binary saving of array in a file works? [C++]为什么在文件中二进制保存数组有效? [C++]
【发布时间】:2011-06-21 12:15:54
【问题描述】:

这里是 C++ 新手。

我正在尝试找出将缓冲区写入文件的以下行:

fOut.write((char *)&_data, sizeof(_data));

_data = 整数数组...

我有几个问题:

  1. &_data 是数组第一个元素的地址吗?
  2. 无论它是什么地址,是否意味着我们只保存数组的地址?那我释放后怎么还能访问数组呢?
  3. 我不应该通过sizeof(_data)*arrLength吗?传递 int 的大小(在这种情况下)而不是整个数组的大小是什么意思?
  4. 在处理地址时,转换为 char* 是什么意思?

非常感谢您的澄清。

【问题讨论】:

  • 更好地显示_data准确定义。无论如何,我对& 持怀疑态度,这是准确的工作代码吗?
  • _data 只是一个数组......保存在堆上。是的,它有效:)

标签: c++ arrays file binary export


【解决方案1】:

与您的评论相反,数组必须是自动或静态存储持续时间,sizeof 才能工作。

  1. 应该只是(char*)_data。数组名称隐式转换为指向第一个元素的指针。

  2. 不,write 需要一个指针,并存储在该位置找到的内容,而不是该位置的地址。

  3. 没有。由于_data 是一个数组,所以sizeof (_data) 是数组中所有元素的累积大小。如果_data 是一个指针(例如当一个数组在堆上动态分配时),你会想要numElems * sizeof(_data[0])。将指针的大小乘以元素的数量并没有帮助。

  4. 这意味着该地址的内容将被视为一系列单独的字节,失去了它可能具有的任何数字含义。这通常用于执行高效的数据批量复制,无论是从文件中复制还是从文件中复制,或者使用memcpy/memmove。数据类型应该是 POD(plain old data),否则你会得到意想不到的结果。

如果_data 是指向从堆分配的数组的指针,正如您的评论所暗示的那样,那么代码被严重破坏了。在这种情况下,您只保存地址,如果您将文件加载回程序的同一个实例,它可能会工作,但这只是因为它发现数据仍在内存中的同一地址。数据实际上不会在文件中,如果您在加载文件之前重新启动程序,您会发现数据已经消失了。进行我在 (1) 和 (3) 中提到的更改,以保存完整的数组,无论它是自动分配、静态分配还是动态分配。

【讨论】:

  • 为什么需要automaticstatic 才能使sizeof 工作?来源?
  • @Muggen:因为动态分配返回一个指针,而sizeof 一个指针不是内容的大小。但是不要将auto 关键字带入其中,这不再意味着自动存储持续时间。
  • 修复了auto。好的,我明白你的意思了。 +1
  • 很抱歉误导了大家。数组是动态的,所以 _data 是一个指向数组的指针。我感到困惑的原因是代码几乎完全按照我在第一篇文章中提到的方式运行。我最终做的是: fout.write((char )_data, sizeof(T)_size);
【解决方案2】:

转换成 char* 是什么意思 处理地址时?

想象一下这个简单的例子

int x = 12;
char * z = (char *)&x;

并假设int 的架构为 4 字节长。来自 C++ 标准 sizeof(char)==1

在表达式char * z char * 部分,你可以说它被用于指针运算

在我给出的示例的第二行,z 现在指向x 拥有的第一个(4 个字节中的)。执行++z; 将使z 指向(在我的示例中)4byte int 的第二个字节

你可以说声明的左边部分用于指针运算,以简化事情。 ++(char *) 会将您移动一个字节,而 ++(int *) 会将您移动相应的字节数 int 在内存中占用。

【讨论】:

    【解决方案3】:
    1. 是的
    2. 不,write使用这个地址作为第一个位置,通过sizeof(_data)读取整个数组
    3. sizeof(_data) 将返回的整个数组的大小与 sizeof(int) 不同
    4. 表示数据将被逐字节读取,这是写入所需的指针,因为它以二进制格式(逐字节)写入

    【讨论】:

    • 谢谢,但是...我已经检查过了,无论我的数组大小,sizeof(_data) 返回 4...所以我猜它是 int 的大小。
    • 我现在写了 cout
    • @user,_data 的类型是什么?
    • 你是动态分配数组吗?在那种情况下 _data 实际上是一个指针,上面的答案会改变。如果_data是指向堆上动态数组sizeof(_data)=4的指针,&_data != &_data[0] 因为一个是指针地址存放的地址,另一个是数组第一个元素的地址跨度>
    • 作为动态分配的数组,_data使用不当,你的代码不正确。
    【解决方案4】:

    1) 是的,&_data 是数组第一个元素的地址。
    2) 不,write() 从地址 &_data
    开始写入您通过 sizeof(_data) 指定的字节数 3) 如果 _data 是指向数组的指针,您将传递 sizeof(int)*arrLength,但由于它,因此数组 sizeof() 返回正确的大小。
    4)不知道。 ;)

    【讨论】:

      【解决方案5】:

      阅读:http://www.cplusplus.com/reference/iostream/ostream/write/

      1. 应该是。
      2. 如果您调用“fstream.write(a,b)”,那么它会从位置 a 开始将 b 个字节写入文件(即地址指向的内容);
      3. 它应该是以字节或字符为单位的大小。
      4. 不多,类似于用更文明的语言将内容转换为 byte[]。

      顺便说一句,它只适用于其中包含简单值的简单数组...

      我建议您查看 >>

      【讨论】:

        【解决方案6】:

        &_data 是数组第一个元素的地址吗?

        是的,是的。 这是在 C 和 C++ 中将“引用”传递给数组的常用方法。如果您将数组本身作为参数传递,则整个数组内容将被复制,这通常是浪费且不必要的。 更正:您可以传递&_data,也可以只传递@987654322 @。无论哪种方式,都不需要将数组复制到堆栈中。

        不管是什么地址,是不是意味着我们只保存了数组的地址?那为什么我把他从内存中删除后还能访问数组呢?

        不,该方法使用它获得的地址来读取数组内容;正如您所指出的,仅保存内存地址是没有意义的。

        我不应该传递 sizeof(_data)*arrLength 吗?我是说... 传递大小的逻辑是什么 int (在这种情况下)而不是大小 整个数组的?

        不,sizeof(_data) 是数组的大小,而不是一个成员的大小。无需乘以长度。

        在处理地址时,转换为 char* 意味着什么?

        转换为 char* 意味着数组作为字节列表访问;这是访问和写入原始值所必需的。

        【讨论】:

        • 如果你传递一个数组名,你传递的是指针。除非它被包装在某种类中,否则数组本身不会被传递。
        • @David:是的,感谢您的更正。我混淆了数组和结构的行为。已更正。
        猜你喜欢
        • 1970-01-01
        • 2020-10-31
        • 2013-08-17
        • 1970-01-01
        • 1970-01-01
        • 2018-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多