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

Qua*_*key 16 c++ floating-point casting

注意:我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?
}
Run Code Online (Sandbox Code Playgroud)

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

AnT*_*AnT 26

嗯,static_cast是"安全的"并且已经定义了行为,但这可能不是你需要的.将整数值转换为float类型只会尝试在目标浮点类型中表示相同的整数值.即5类型int将变为5.0类型float(假设它可以精确表示).

您似乎要做的是float在声明为Uint32变量的内存块中构建值的对象表示.要生成结果float值,您需要重新解释该内存.这将通过以下方式实现reinterpret_cast

assert(sizeof(float) == sizeof val);
return reinterpret_cast<float &>( val );
Run Code Online (Sandbox Code Playgroud)

或者,如果您愿意,也可以使用相同内容的指针版本

assert(sizeof(float) == sizeof val);
return *reinterpret_cast<float *>( &val );
Run Code Online (Sandbox Code Playgroud)

虽然这种类型惩罚不能保证在遵循严格别名语义的编译器中工作.另一种方法是这样做

float f;

assert(sizeof f == sizeof val);
memcpy(&f, &val, sizeof f);

return f;
Run Code Online (Sandbox Code Playgroud)

或者您可以使用众所周知的联合hack来实现内存重新解释.这在C++中是正式非法的(未定义的行为),这意味着此方法只能用于支持它作为扩展的某些实现

assert(sizeof(float) == sizeof(Uint32));

union {
  Uint32 val; 
  float f;
} u = { val };

return u.f;
Run Code Online (Sandbox Code Playgroud)