reinterpret_cast一个整数浮动是否安全?

时间:2012-12-20 23:53:29

标签: c++ casting floating-point

注意:我最初错误地询问了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?
}

我希望这个软件尽可能便携。

2 个答案:

答案 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(这两个标准的浮点数格式相同,我不完全确定细节差异是什么,是诚实)。因此,如果您的计算机使用不同的浮点格式,它将会失败。我不确定是否有任何方法可以检查,除了可能在某处存储了一组固定的字节,以及浮点数中的预期值,然后转换值并查看它是否“正确”出现。