注意:我最初错误地询问了static_cast
;这就是为什么最佳答案首先提到static_cast
。
我有一些带有少量字节序浮点值的二进制文件。我想以与机器无关的方式阅读它们。我的字节交换例程(来自SDL)在无符号整数类型上运行。
简单地在整数和浮点数之间进行投射是否安全?
float read_float() {
// Read in 4 bytes.
Uint32 val;
fread( &val, 4, 1, fp );
// Swap the bytes to little-endian if necessary.
val = SDL_SwapLE32(val);
// Return as a float
return reinterpret_cast<float &>( val ); //XXX Is this safe?
}
我希望这个软件尽可能便携。
答案 0 :(得分:26)
嗯,static_cast
是“安全的”并且已经定义了行为,但这可能不是您需要的。将整数值转换为float类型只会尝试在目标浮点类型中表示相同的整数值。即5
类型的int
将变为类型5.0
的{{1}}(假设它可以准确表示)。
您似乎正在做的是在声明为float
变量的内存块中构建float
值的对象表示。要生成结果Uint32
值,您需要重新解释该内存。这可以通过float
reinterpret_cast
或者,如果您愿意,还可以使用相同内容的指针版本
assert(sizeof(float) == sizeof val);
return reinterpret_cast<float &>( val );
虽然不能保证这种类型 - 双关语在遵循严格别名语义的编译器中有效。另一种方法是这样做
assert(sizeof(float) == sizeof val);
return *reinterpret_cast<float *>( &val );
或者您可以使用众所周知的联合黑客来实现内存重新解释。这在C ++中是正式非法的(未定义的行为),这意味着此方法只能用于支持它作为扩展的某些实现
float f;
assert(sizeof f == sizeof val);
memcpy(&f, &val, sizeof f);
return f;
答案 1 :(得分:3)
简而言之,这是不正确的。您正在将一个整数转换为float,并且编译器将在此时将其解释为整数。上面提出的工会解决方案有效。
与联盟做同样事情的另一种方法是使用它:
return *reinterpret_cast<float*>( &val );
它与上面的联合解决方案同样安全/不安全,我肯定会推荐一个断言来确保float与int的大小相同。
我还要警告,有些浮点格式不符合IEEE-754或IEEE-854(这两个标准的浮点数格式相同,我不完全确定细节差异是什么,是诚实)。因此,如果您的计算机使用不同的浮点格式,它将会失败。我不确定是否有任何方法可以检查,除了可能在某处存储了一组固定的字节,以及浮点数中的预期值,然后转换值并查看它是否“正确”出现。