提问人:RookieCPP 提问时间:12/18/2022 最后编辑:user3840170RookieCPP 更新时间:12/19/2022 访问量:502
当指向 32 位整数的指针被强制转换为指向浮点数的指针并取消引用时,会发生什么情况?
What happens when a pointer to a 32-bit integer is cast to a pointer to a float and dereferenced?
问:
我看到了这个演员表:
const std::uint32_t tmp = (some number);
float ToFloat = *(float*)(&tmp);
但是在投掷时,错误的数字会进入浮点数。此外,如果我使用静态强制转换,那么它是正确强制转换的。
- 为什么会这样?
- static_cast究竟是如何工作的?
*(float*)(&Tmp)
意味着我们正在尝试取消引用指向浮点数的指针,浮点数位于地址 .这是对的吗?&tmp
答:
为什么会这样?
该程序具有未定义的行为,因为您通过 .这在 C++ 中是不允许的。int
float
static_cast究竟是如何工作的?
在这种情况下,它执行的转换与执行的转换相同。也就是说,它将 转换为 并将其分配给 。float ToFloat = Tmp;
int
float
ToFloat
*(float*)(&Tmp)
意味着我们正在尝试取消引用指向浮点数的指针,浮点数位于地址 &Tmp。这是对的吗?
没有 at ,只有一个 .但是,您可以告诉编译器指针指向 并取消引用该指针。s 和 s 的位模式非常不同,因此它不仅具有未定义的行为,而且不太可能获得正确的结果。float
&Tmp
int
float
int
float
评论
-fno-strict-aliasing
Tmp
static_cast
*(float*)(&Tmp)
存储整数
整数存储在其二进制(以 2 为基数)表示形式中。 占用 32 位。int32_t
存储浮点数
在大多数 C++ 编译器中,使用称为 IEEE 754 的标准来存储浮点数和双精度值。这与整数的存储方式有很大不同。
您可以使用某种 IEEE-754 浮点转换器自行检查数字的存储方式。
例
让我们考虑一个数字 5 的简单例子。
const uint Tmp = 5;
Tmp
将像存储在内存中一样存储,因此将指向相同。0x00000005
&Tmp
float ToFloat = *(float*)(&Tmp);
将其转换为浮点指针将被视为 IEEE 754 格式,具有值。0x00000005
7.00649232162e-45
static_cast
静态强制转换使用安全的隐式转换在兼容类型之间执行转换。
请注意,您正在将问题中的 from 转换为 ,这不是一个安全的转换。您可以安全地从 转换为 。int*
float*
int
float
const uint32_t Tmp = 5;
float ToFloat = (float)Tmp; // 5
有关static_cast转换的更多信息。
评论
此代码尝试执行的操作是将浮点数的 32 位表示形式转换为实际的浮点值。IEEE 754 二进制浮点值(大多数情况下)是 (−1) 形式的数字的表示形式,× m × 2e。对于给定的浮点格式,机器字中一定数量的位被分配给 s(符号位)、m(尾数或有效位)和 e(指数位)中的每一个。这些位可以直接在位表示中操作,以构造任何可能的浮点值,绕过语言提供的普通算术运算的通常抽象。Aryan 的回答中提到的转换器是探索其工作原理的好方法。
不幸的是,这段代码不是符合标准的 C++(或者,实际上是 C),这要归功于一种叫做严格别名的东西。简而言之:如果一个变量被声明为整数类型,则只能通过指向同一整数类型的指针来访问它。不允许通过指向其他类型的指针访问它。
或多或少得到官方认可的版本是:
inline static float float_from_bits(std::uint32_t x) {
float result;
static_assert(sizeof(result) == sizeof(x),
"float must be 32 bits wide");
std::memcpy(&result, &x, sizeof(result));
return result;
}
或者,在 C++20 中,简单地 .这仍然不能完全保证按照标准返回预期结果,但至少它不违反该特定规则。std::bit_cast<float>(x)
直接会将整数转换为浮点值,表示(近似)相同的数量。这不是直接的位转换:执行它需要计算 s、m 和 e 的适当值,并根据数字格式将它们放在适当的位置。static_cast
下一个:C 中的浮点除法用于大数
评论
auto value = static_cast<float>(tmp);
float ToFloat = *reinterpret_cast<float*>(const_cast<uint32*>(&Tmp));
&Tmp
uint32 const*
float
static_cast
uint32
float
Tmp
ToFloat
Tmp