这是一个非常简单的 C/C++ 代码,这让我感到惊讶,因为它没有给出相同的结果。
float f = -123.123f;
unsigned u1 = -123.123f;
unsigned u2 = f;
printf("%d %d\n", u1, u2); // 0 -123
printf("%u %u\n", u1, u2); // 0 4294967173
Run Code Online (Sandbox Code Playgroud)
输出给出:
float f = -123.123f;
unsigned u1 = -123.123f;
unsigned u2 = f;
printf("%d %d\n", u1, u2); // 0 -123
printf("%u %u\n", u1, u2); // 0 4294967173
Run Code Online (Sandbox Code Playgroud)
为什么结果不会一样呢?
这是令人担忧的,因为具有相同含义的符号在语言中无法替换。
我在programiz.com 网站上使用C++ 编译器测试了该示例。
我预计结果是相同的。
谢谢您的回答,让我们忘记打印部分。可以理解,它是未定义的,因此各个值可能会有所不同。
Eri*_*hil 12
C 标准未定义将小于或等于 \xe2\x88\x921 的浮点数转换为无符号整数类型的行为。C 2018 6.3.1.4 1 说:
\n\n\n当实浮点类型的有限值转换为除 之外的整数类型时
\n_Bool,小数部分将被丢弃(即该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为未定义。
因此,对于-123.123f,小数部分将被丢弃,留下 \xe2\x88\x92123。那么整数部分 \xe2\x88\x92123 无法用无符号类型表示,因此未定义行为。
在大多数无符号类型的运算中,数学结果以模 2 w进行包装,其中w是无符号类型的宽度(以位为单位)。例如,unsigned u = 0u - 123u;orunsigned u = -123;都会包装数字并产生定义的结果(对于 16 位,这将是 65,536 \xe2\x88\x92 123 = 65,413 ,unsigned int对于 32 位,这将是 4,294,967,296 \xe2\x88\x92 123 = 4,294,967,173 unsigned int) 。对于浮点转换,C 标准并未规定会发生这种换行。行为未定义。
在您的特定情况下可能发生的情况是,在编译时,编译器使用自己的代码来生成一些结果,以将浮点数转换为unsigned,并且此代码生成零,而对于从变量的转换,编译器生成执行转换的处理器指令,该处理器指令生成与 \xe2\x88\x92123 (两个 \xe2\x80\x99 补码)或 4,294,967,173 (无符号)相对应的位。然后,当这些位被发送到printf用 打印时%d,它将这些位的解释打印为int,产生 \xe2\x80\x9c-123\xe2\x80\x9d 的输出。(这是进一步未定义的行为,%d不应与 an 一起使用unsigned int,并且 C 标准没有定义这种不匹配会发生什么情况。但是,将 的位解释unsigned int为 anint是很常见的。)
| 归档时间: |
|
| 查看次数: |
252 次 |
| 最近记录: |