int main()
{
printf("Hello World\n");
int x = -10;
unsigned y = 25;
float z = x*y;
printf("x=%d,y=%u,z=%f\n",x,y,z);
return 0;
}
当我运行上面的代码时,我得到以下输出:
Hello World
x=-10,y=25,z=4294967046.000000
我的问题是:
对于第二个 printf,我希望 z=(float) ( (unsigned)(-10)*25 ) = (float) (4294967286 x 25) = (float) 107374182150
,我是什么这里不见了?
最佳答案
这就是正在发生的事情。根据 C11 6.3.1.8 通常的算术转换
(“否则”在这里发挥作用,因为前面的段落讨论了当任一类型已经是浮点时会发生什么):
Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.
这意味着您的 -10
的有符号值变成了 0xffff'fff6
或 4,294,967,286
的无符号值。将其乘以 25
得到 107,374,182,150
或 0x18'ffff'ff06
(这是您想要的结果)。
然而,此时,还没有进行任何 float
计算,乘法是纯整数计算,结果值将是整数。再加上您的无符号整数是 32 位长,这意味着它会被截断为 0xffff'ff06
或 4,294,967,046
。
然后你把 that 放到 float
中。
要修复此问题以匹配您的预期结果,您应该更改他的表达式以强制执行此操作:
float z = 1.0f * (unsigned)x * y;
这会将 int * unsigned-int
计算更改为 float * unsigned-int * unsigned-int
之一。 unsigned
转换首先确保 x
将被转换为等效的无符号值,并且与 1.0f
的乘法确保在 中完成乘法>float
arena 以避免整数截断。
关于C算术转换将无符号与有符号相乘并产生 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64547321/