为什么将数组二进制保存在文件中有效? [C++]
这里是 C++ 新手。
我试图找出以下将缓冲区写入文件的行:
fOut.write((char *)&_data, sizeof(_data));
_data = 整数数组...
我有几个问题:
&_data
是第一个元素的地址数组的?- 无论它是什么地址,是否意味着我们只保存数组的地址?那么为什么我释放数组后仍然可以访问该数组呢?
- 我不应该传递
sizeof(_data)*arrLength
吗?传递 int 的大小(在本例中)而不是整个数组的大小有何意义? - 处理地址时,转换为
char*
意味着什么?
我真的很感激一些澄清。
C++ newbie here.
I'm trying to figure out the following line that writes a buffer into a file:
fOut.write((char *)&_data, sizeof(_data));
_data = array of integers...
I have a couple of questions:
- Is
&_data
the address to the first element of the array? - Whatever address it is, does that mean that we only save the address of the array? then how come I still can access the array after I free it?
- Shouldn't I pass
sizeof(_data)*arrLength
? what is the meaning of passing the size of int (in this case) and not the size of the entire array? - What does casting into
char*
mean when dealing with addresses?
I would really appreciate some clarifications.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
与您的评论相反,数组必须是自动或静态存储持续时间才能使
sizeof
工作。它应该只是
(char*)_data
。数组的名称隐式转换为指向第一个元素的指针。不,
write
需要一个指针,并存储在该位置找到的内容,而不是该位置的地址。没有。由于
_data
是一个数组,因此sizeof (_data)
是数组中所有元素的累积大小。如果_data
是一个指针(例如当在堆上动态分配数组时),您可能需要numElems * sizeof(_data[0])
。将指针的大小乘以元素的数量没有任何帮助。这意味着该地址的内容将被视为一系列单独的字节,失去它可能具有的任何数字含义。这样做通常是为了执行高效的数据批量复制,无论是到文件还是从文件复制,或者使用memcpy/memmove。数据类型应该是 POD(普通旧数据),否则您将得到意外结果。
如果
_data
是一个指向从堆分配的数组的指针,正如您的评论所暗示的那样,那么代码就被严重破坏了。在这种情况下,您只保存地址,如果您将文件加载回程序的同一实例,它可能看起来可以工作,但这只是因为它发现数据仍在内存中的同一地址处。数据实际上并不在文件中,如果您在加载文件之前重新启动程序,您会发现数据消失了。进行我在 (1) 和 (3) 中提到的更改,以便保存完整的数组,无论它是自动分配、静态分配还是动态分配。Contrary to your comment, the array must be automatic or static storage duration in order for
sizeof
to work.It should be just
(char*)_data
. The name of an array implicitly converts to a pointer to the first element.No,
write
expects a pointer, and stores the content found at that location, not the location's address.No. Since
_data
is an array,sizeof (_data)
is the cumulative size of all elements in the array. If_data
were a pointer (such as when an array is dynamically allocated on the heap), you would wantnumElems * sizeof(_data[0])
. Multiplying the size of a pointer by the number of elements isn't helpful.It means that the content at that address will be treated as a series of individual bytes, losing whatever numeric meaning it might have had. This is often done to perform efficient bulk copy of data, either to and from a file, or with
memcpy
/memmove
. The data type should be POD (plain old data) or you'll get unexpected results.If
_data
is a pointer to an array allocated from the heap, as your comment suggests, then the code is badly broken. In that case, you are saving just the address, and it may appear to work if you load the file back into the same instance of your program, but that's just because it's finding the data still in memory at the same address. The data wouldn't actually be in the file, and if you re-started the program before loading the file, you'd find that the data was gone. Make the changes I mentioned in both (1) and (3) in order to save the complete array regardless of whether it's allocated automatic, static, or dynamically.想象一下这个简单的例子
,并假设一个
int
长度为 4 个字节的架构。来自 C++ 标准sizeof(char)==1
。在表达式
char * z
的char *
部分,您可以说它被用于我给出的示例的第二行的指针算术,发生的情况是 < code>z 现在指向
x
所具有的第一个(4 个字节)。执行++z;
将使z
指向(在我的示例中)4byteint
的第二个字节。声明的一部分用于指针算术,以简化事情。
++(char *)
会将您移动一个字节,而++(int *)
会将您移动相应的字节数int< /code> 占用内存。
Imagine this simple example
And assume an architecture where
int
is 4 bytes long. From the C++ Standardsizeof(char)==1
.On the expression
char * z
thechar *
part, you could say that is being used for pointer arithmeticon the Second line of the example I gave, what happens is that
z
now points to the first (out of 4 bytes) thatx
has. Doing a++z;
will makez
point to the Second Byte of the (in my example) 4byteint
You could say that the left part of a declaration is used for pointer arithmetic, to simplify things. a
++(char *)
would move you by one byte, while a++(int *)
would move you by the corresponding number of bytesint
occupies on the memory.1) 是的,&_data 是数组第一个元素的地址。
2) 不,write() 会从地址 &_data
开始写入您通过 sizeof(_data) 指定的字节数
3) 如果 _data 是指向数组的指针,则可以传递 sizeof(int)*arrLength,但由于它是数组,因此 sizeof() 返回正确的大小。
4)不知道。 ;)
1) Yes, &_data is the address of the first element of your array.
2) No, write() writes the number bytes you have specified via sizeof(_data) starting at address &_data
3) You would pass sizeof(int)*arrLength if _data is a pointer to an array, but since it is an array sizeof() returns the correct size.
4) don't know. ;)
阅读此内容: http://www.cplusplus.com/reference/iostream/ostream/write /
顺便说一句,它只适用于其中包含简单值的简单数组...
我建议您查看>> <<运营商。
read this : http://www.cplusplus.com/reference/iostream/ostream/write/
By the way, it will only work on simple arrays with simple values inside them...
i suggest you look into the >> << operators .
是的。
这是在 C 和 C++ 中将“引用”传递给数组的常用方法。如果您将数组本身作为参数传递,则整个数组内容将被复制,这通常是浪费且不必要的。更正:您可以传递&_data,或只是
_data
。无论哪种方式,数组都不需要复制到堆栈中。不,该方法使用它获得的地址来读取数组内容;正如您所指出的,仅保存内存地址是没有意义的。
不,
sizeof(_data)
是数组的大小,而不是单个成员的大小。无需乘以长度。转换为 char* 意味着该数组作为字节列表进行访问;这是访问和写入原始值所必需的。
Yes, it is.
This is the usual way to pass a "reference" to an array in C and C++. If you passed the array itself as a parameter, the whole array contents would be copied, which is usually wasteful and unnecessary.Correction: You can pass either&_data
, or just_data
. Either way, the array does not need to be copied to the stack.No, the method uses the address it gets to read the array contents; just saving the memory address would be pointless, as you point out.
No,
sizeof(_data)
is the size of the array, not of one member. No need to multiply by length.Casting to char* means that the array is accessed as a list of bytes; that's necessary for accessing and writing the raw values.