复制浮点数的字节模式不起作用



我目前正在自学c++,并尽我所能学习有关内存的知识。我发现你可以使用char指针来复制int类型的位模式,并将其存储在内存中。

#include <iostream>
using namespace std;
int main()
{
int x = 20;
char* cp = new char[sizeof(int)];
cp[0] = *((char*)&x);
cp[1] = *((char*)&x+1);
cp[2] = *((char*)&x+2);
cp[3] = *((char*)&x+3);
std::cout << (int)*cp; // returns 20; 

return 0;
}

上面的代码工作,当我将cp转换为int时,编译器一次读取4个字节,我得到正确的数字是20。

但是把它改成float:

#include <iostream>
using namespace std;
int main()
{
float x = 20;
char* cp = new char[sizeof(float)];
cp[0] = *((char*)&x);
cp[1] = *((char*)&x+1);
cp[2] = *((char*)&x+2);
cp[3] = *((char*)&x+3);
std::cout << (float)*cp; // returns 0.

return 0;
}

返回0。现在我有点困惑了。如果我复制每一个字节,为什么它还是给我一个0?如果有人能帮我理解这一点,那将是非常棒的。

(int)*cp;首先对指针解引用,返回一个char值,该值现在被静态转换为整数。这将只适用于char可以存储的范围-0 255-128 127,并且需要一个小端系统。

似乎如何修复它的方式是*reinterpret_cast<float*>(cp);*((float*)cp)。两者都是错误的,并且会导致未定义的行为,因为它们违反了严格的混叠规则。

严格混叠规则规定,只有在指针指向的内存位置存在T类型的对象时,才能解引用指向T的指针。除了char,std::byte,unsigned char。这意味着通过转换到char来检查任何类型都是正确的,但不能简单地将一堆字节解释为随机的T

序列化和反序列化对象的正确方法是:

#include <iostream>
using namespace std;
int main() {
float x = 20.0f;
// This is safe.
char* cp1 = reinterpret_cast<char*>(&x);
// Also safe because there is a float object at cp1.
std::cout << *reinterpret_cast<float*>(cp1);
// No need for dynamic allocation.
char cp2[sizeof(float)];
// Copy the individual bytes into a buffer.
//  = Serialize the object.
std::memcpy(cp2, &x, sizeof(x));
// NOT SAFE, UNDEFINED BEHAVIOUR
// There is no float object at cp2.
std::cout << *reinterpret_cast<float*>(cp2);
// Deserialization through copy
float y;
std::memcpy(&y, cp2, sizeof(y));
// Safe
std::cout << y;
return 0;
}

最新更新