我已经打开了要写入的ofstream文件,我想写一个unsigned int的4个字节。我希望int为零,所以我尝试这样做:
outFile.write((char*)&unsigned int(0), sizeof(unsigned int)); // Expression must be an lvalue
unsigned int a = 0;
outFile.write((char*)&a, sizeof(unsigned int)); // This works fine
我的理解是,unsigned int之类的生命周期一直到该行的末尾,换句话说,被下一个分号破坏。 通过事先创建本地来写这样的东西是唯一的方法吗?另外,我注意到fstreams需要使用char指针,我想知道在复制内容时是否需要谨慎,例如在二进制模式下我希望它能像在内存中那样完全写入字节,但是例如如果我有一个unsigned int 255它会将这个无符号的int位复制为bit吗?在处理原始内存复制时,这不应该像一个空指针吗?
答案 0 :(得分:1)
当局部变量超出范围时会被销毁。这通常是在下一个结束时。
outFile.write((char*)&unsigned int(0)
试图获取不存在的东西的地址。您必须首先实例化变量
{
....code...
{
unsigned int a = 0;
outFile.write((char*)&a, sizeof(unsigned int));
}
<- legally a no longer exists
unsigned int b = 0; // b *might* now occupy the same stack space that was used to store a. then again it might not, it depends on the compiler.
}
<- b no longer exists.
您可以使用非正统方式访问超出范围的局部变量,具体取决于编译器如何构建堆栈帧,以前由所述本地占用的空间可能会或可能不会被现在存在的东西使用。
outFile.write((char*)&a, sizeof(unsigned int));
将尝试写入与unsigned int一样多的位,用于位。
但我会用
outFile.write((char*)&a, sizeof(a));
因为硬编码大小可能会让您后来感到头疼。如果你更改a的数据类型让我们说双倍,但你忘了将sizeof更新为sizeof(double)
答案 1 :(得分:1)
定义变量(左值)是访问int unsigned int a = 0;
的内存的唯一方法
rvalues可能永远不会存在于内存中
(3 + 4)
可以在编译时优化到7
。
以下是差异的一些例子
Difference between rvalue and lvalue
This question explains some of the pitfalls of writing the raw bytes of an int
答案 2 :(得分:1)
除非将其转换为左值,否则不能取rvalue的地址。然后,编译器将创建一个临时变量并获取其地址。
template<typename T>
remove_reference_t<T>& rtolvalue_cast(remove_reference_t<T> &&t)
{
return static_cast<remove_reference_t<T> &>(t);
}
然后你可以写:
outFile.write((char*)& rtolvalue_cast<unsigned int>(0), sizeof(unsigned int));
从技术上讲,这个演员是std::forward<T>
的一个遥远的亲戚,除了它已经在static_assert
的库中被禁用之外,它也可以做到这一点,并且可能有很好的理由。
这个演员更像是一个技术人工制品而非现实。
而是创建一个临时变量并获取其地址。