将整数重新解释为浮点数是否安全?

新手上路,请多包涵

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

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

原文由 Daniel Hanrahan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 533
1 个回答

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

您似乎正在做的是在声明为 Uint32 变量的一块内存中构建 float 值的对象表示。要产生结果 float 值,您需要 重新解释 该内存。这将通过 reinterpret_cast

 assert(sizeof(float) == sizeof val);
return reinterpret_cast<float &>( val );

或者,如果您愿意,也可以是同一事物的指针版本

assert(sizeof(float) == sizeof val);
return *reinterpret_cast<float *>( &val );

尽管这种类型的双关语不能保证在遵循严格别名语义的编译器中工作。另一种方法是这样做

float f;

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

return f;

或者你可以使用著名的 union hack 来实现内存重新解释。这在 C++ 中是正式非法的(未定义行为),这意味着此方法只能用于支持它作为扩展的某些实现

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

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

return u.f;

原文由 AnT stands with Russia 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题