C算术转换将无符号与有符号相乘并产生 float

标签 c

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'fff64,294,967,286 的无符号值。将其乘以 25 得到 107,374,182,1500x18'ffff'ff06(这是您想要的结果)。

然而,此时,还没有进行任何 float 计算,乘法是纯整数计算,结果值将是整数。再加上您的无符号整数是 32 位长,这意味着它会被截断为 0xffff'ff064,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/

相关文章:

c - free()失败

c - 将字符串分成 'first' 和 'second'

c - 输入 fget 时检测到堆栈崩溃

C 指针问题

c - 如何可靠地比较 Haskell 和 C 的运行时间?

C中通过管道进行通信

c - Dev-C++ 和 xcode 编译器的不同输出

c - 我应该在 C 中将 stdout 和 stdin 设置为无缓冲吗?

c - 错误(DCC :1086):redeclaration of uint16_t

c - 给定层序遍历如何构造树?