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

Copying Byte Pattern For Floats Does Not Work

我目前正在自学 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。

但是将其更改为浮点数:

#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;
}

returns 0.现在我在这里有点困惑。如果我复制每个字节,为什么它仍然给我一个 0?如果有人能帮助我理解这一点,那就太棒了。

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

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

严格的别名规则指出,只有在指针指向的内存位置存在 T 类型的对象时,才能取消引用指向 T 的指针。 charstd::byteunsigned 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;
}