无符号u = *(unsigned *)& x的含义是什么?在C++ x在哪里浮动变量?
由于我的数值分析课程考试即将到来,所以我正在寻找一个实现代码以表示C/C ++中的浮点数?然后,我从Github中的代码中找到了一条线。您能告诉我,下面的代码段中第二行的含义是什么,以及为什么这很重要?
float x = ...;
unsigned u = *(unsigned*)&x;
Since my Numerical Analysis course exam is near, I was searching for a implementation code to to represent floating point numbers in C/C++? Then I found a line from one the codes in github. Can you please tell me, what is the meaning of the second line in the code snippet below, and how and why this is important?
float x = ...;
unsigned u = *(unsigned*)&x;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
unsigned
只是unsigned int
的简短,并且使用C ++ - 样式铸造该行将转换为以下内容,但是在下面阅读为什么在任何一种情况下都会导致不确定的行为。
并不明显。
(我建议不要像问题中所示的行中使用C风格的铸件一样,因为C ++的样式 /code>变量,然后该行试图重新解释
float
变量的对象表示为nosigned int
的对象表示,基本上是重新诠释float
的内存为intemed int
的内存,然后存储insted int
值,在u
中与该表示相对应的值。步骤的步骤,
& x
是x
typefloat*
的指针; x)是指向x
的指针,但现在类型为intemed> intemed int*
。然后*reinterpret_cast< unsigned int*>(& x)
应该解释int
变量,从指向内存的位置检索unsigned int*
指针指向float
floatinted int
值,好像在其中存储的字节代表无符号int
值,而不是float
值。最后,unsigned int u =
应该使用该值来初始化u
。这会导致不确定的行为,因为它是通过
float
对象通过无符号的INT*
指针访问float
对象。一些编译器具有可以允许此功能的选项(在float
和unsigned Int
具有兼容大小和对齐方式的假设下),但是标准C ++不允许使用。语言本身。通常,每当您看到
reinterpret_cast
(或可能解析为reinterpret_cast
)的C风格铸件时,如果您不知道确切的情况,您可能会导致不确定的行为你在做。由于C ++ 20在没有未定义行为的情况下执行此操作的正确方法是使用
std :: bit_cast
:或者在C ++之前使用
std :: memcpy
:大小验证由
std :: bit_cast
自动完成。即使没有C ++ 20,也可能是一个好主意,最好将static_assert
和memcpy
在类似的通用函数中进行重复使用。这两个仍然都要求
x
的表示也是u
的有效表示。否则,行为仍然不确定。我不知道是否有任何C ++实现,在float->未签名
案例。另外,请注意:C是另一种语言。例如,规则在C中很可能有所不同。例如,在
>(unsigned*)
cast可以解决的reinterpret_cast
显然没有reinterpret_cast
。但是,在这种情况下,C的混叠规则将产生同等效果。unsigned
is just short forunsigned int
and using C++-style casts the line would translate toHowever read below why this causes undefined behavior in either case.
(I recommend to not use C-style casts as in the line shown in the question, since it is not obvious to which C++-style cast they resolve.)
If
x
is afloat
variable, then the line is trying to reinterpret the object representation of thefloat
variable as the object representation of anunsigned int
, basically to reinterpret thefloat
's memory as the memory of anunsigned int
, and then stores theunsigned int
value corresponding to that representation inu
.Step for step,
&x
is a pointer tox
of typefloat*
,reinterpret_cast<unsigned int*>(&x)
is a pointer tox
, but now of typeunsigned int*
. And then*reinterpret_cast<unsigned int*>(&x)
is supposed to dereference thatunsigned int*
pointer to thefloat
variable to retrieve anunsigned int
value from the pointed-to memory location as if the bytes stored there represented anunsigned int
value instead of afloat
value. Finallyunsigned int u =
is supposed to use that value to initializeu
with it.That causes undefined behavior because it is an aliasing violation to access a
float
object through aunsigned int*
pointer. Some compilers have options which can be enabled to allow this (under the assumption thatfloat
andunsigned int
have compatible size and alignment), but it is not permitted by the standard C++ language itself.Generally, whenever you see
reinterpret_cast
(or a C-style cast that might resolve to areinterpret_cast
), you are likely to cause undefined behavior if you don't know exactly what you are doing.Since C++20 the correct way to do this without undefined behavior is using
std::bit_cast
:or before C++20 using
std::memcpy
:The size verification is done by
std::bit_cast
automatically. Even without C++20 it would probably be a good idea to wrap thestatic_assert
andmemcpy
in a similar generic function for reuse.Both of these still require that the representation of
x
is also a valid representation for au
. Otherwise the behavior is still undefined. I don't know whether there even is any C++ implementation where this doesn't hold for all values in thefloat -> unsigned
case.Also as an additional note: C is a different language. The rules may well be different in C. For example there is obviously no
reinterpret_cast
in C to which the(unsigned*)
cast could resolve and the object model is very different. In this case though, C's aliasing rules will have an equivalent effect.它不是有效的C ++。 (程序的行为)是未定义的。
演员表的表达将导致违反一致性要求(又称“严格的违反违约”)。
请参阅:§6.7内存和对象和§6.8类型 iso/iec JTC1 SC22 WG21 。
问题是显式铸造将成为
reinterpret_cast
:float*
不是 使用无符号*
。您可以做到这一点:
It is not valid C++. The behavior (of the program) is undefined.
The cast expression would cause the alignment requirement to be violated (aka "strict aliasing violation").
See: §6.7 Memory and objects, and §6.8 Types of ISO/IEC JTC1 SC22 WG21.
The problem is the explicit cast will become a
reinterpret_cast
:float*
is not Pointer-Interconvertible withunsigned*
.You could do this, instead:
假设
x
是float
,那么代码是一种hack的方法,可以通过将其钻头直接复制到整数中,即无需执行正常浮动而访问浮子的二进制格式指向整数转换,如果您只是写u = x;
,将会发生。Assuming that
x
isfloat
, then the code is a hacky way to access the binary format of a float by copying its bits directly to an integer, i.e. without doing the normal floating point to integer conversion that would happen if you just wroteu = x;