联合int位使浮点位有时被解释为错误

时间:2019-06-04 00:10:19

标签: c++

当我插入一些花车时,我发现了一些躲闪的问题。我已经简化了问题并尝试了一些测试

#include <iostream>
#include <vector>

std::vector<float> v; // global instance

union{ // shared memory space
    float f; // to store data in interleaved float array
    unsigned int argb; // int color value
}color; // global instance

int main(){
    std::cout<<std::hex; // print hexadecimal

    color.argb=0xff810000; // NEED A==ff AND R>80 (idk why)
    std::cout<<color.argb<<std::endl; // NEED TO PRINT (i really dk why)
    v.insert(v.end(),{color.f,0.0f,0.0f}); // color, x, y... (need the x, y too. heh..)

    color.f=v[0]; // read float back (so we can see argb data)
    std::cout<<color.argb<<std::endl; // ffc10000 (WRONG!)
}

程序打印

ff810000
ffc10000

如果有人可以告诉我,我只是在某个很棒的地方呆呆了。


更新:关闭优化

#include <iostream>

union FLOATINT{float f; unsigned int i;};

int main(){
    std::cout<<std::hex; // print in hex

    FLOATINT a;
    a.i = 0xff810000; // store int
    std::cout<<a.i<<std::endl; // ff810000

    FLOATINT b;
    b.f = a.f; // store float
    std::cout<<b.i<<std::endl; // ffc10000
}

#include <iostream>

int main(){
    std::cout<<std::hex; // print in hex

    unsigned int i = 0xff810000; // store int
    std::cout<<i<<std::endl; // ff810000

    float f = *(float*)&i; // store float from int memory

    unsigned int i2 = *(unsigned int*)&f; // store int from float memory
    std::cout<<i2<<std::endl; // ffc10000
}

解决方案:

#include <iostream>

int main(){
    std::cout<<std::hex;

    unsigned int i=0xff810000;
    std::cout<<i<<std::endl; // ff810000

    float f; memcpy(&f, &i, 4);
    unsigned int i2; memcpy(&i2, &f, 4);

    std::cout<<i2<<std::endl; // ff810000
}

2 个答案:

答案 0 :(得分:4)

您看到的行为是定义明确的IEEE浮点数学。

您存储在argb中的值,当解释为浮点数时,将是SNaN(信令NaN)。当将此SNaN值加载到浮点寄存器中时,通过将最高有效分数位设置为1,它将转换为QNaN(安静NaN)(如果未屏蔽浮点异常,则会引发异常)。

此负载会将您的值从ff810000更改为ffc10000

答案 1 :(得分:3)

写入int,然后从联合中的浮点数读取会导致UB。如果要创建混合值类型的向量,请构造一个结构来保存它们。另外,当您只需要32位时,请勿使用unsigned int。使用uint32_t

#include <iostream>
#include <vector>

struct gldata {
    uint32_t argb;
    float x;
    float y;
};

std::vector<gldata> v;

int main() {
    std::cout << std::hex; // print hexadecimal

    v.emplace_back(gldata{0xff810000, 0.0f, 0.0f});

    std::cout << v[0].argb << "\n"; // 0xff810000
}