当我插入一些花车时,我发现了一些躲闪的问题。我已经简化了问题并尝试了一些测试
#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
}
答案 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
}