#include <stdio.h>
int main()
{
unsigned int count=1;
signed int val = -20;
signed int div=(val/count);
signed int div1=(val/(signed int)count);
printf("div %d div1 %d \n",div,div1);
return 0;
}
输出:
div -20 div1 -20
但如果count = 5则输出:
div 858993455 div1 -4
在count = 5的情况下,signed int被隐式转换为unsigned int,为什么不为count = 1
答案 0 :(得分:5)
signed int div=(val/count);
如果其中一个操作数为int
而另一个操作数为unsigned int
,则int
操作数将转换为unsigned int
。因此,val
转换为unsigned int
,然后除以count
,然后将结果转换回int
。
也就是说,此表达式被评估为
int div = (int)((unsigned int)val / count);
因此,当count == 1
时,结果保持不变,但当count == 5
(unsigned int)val / count
的结果变得小于INT_MAX
时,所以当转换回int
时它不会改变它的(大正值)值。
请注意,严格来说,即使count == 1
结果不一定是-20
,因为从(unsigned int)-20
到int
的转换结果是实现定义的
答案 1 :(得分:1)
没有“隐式类型转换”这样的东西,类型转换是指明确地改变操作数的类型。正确的术语是隐式(类型)转换。
C的基本原则表明编译器可以随意订购或优化您的程序,只要它不会改变程序的结果。
因此,即使编译器发现1除法没有意义并且可以进行优化,它仍然必须考虑由隐式类型转换引起的潜在副作用:它无法优化那些,因为程序员可能故意依赖它们。
在您的特定情况下,signed int div=(val/count)
会强制val
隐式转换为无符号类型。但这并不重要,因为你将结果显示回一个有符号的类型,任何除以1的东西无论如何都将保持不变。因此编译器可以优化整个事物,因为无论是否使用了无符号或有符号算术,结果都是相同的。
如果除以5,则结果在-20/5 = -4
和0xFFFFFFEC/5 = 0xFFFFFFFC
之间变得非常不同。因此,编译器不允许优化隐含转换,因为它会影响结果。
因此,程序员必须知道implicit type conversion rules,以告诉他们自己的源代码行之间实际会发生什么。
答案 2 :(得分:0)
这是the usual arithmetic conversions。你可以在那里找到规则。
实际上,第一个结果是(无符号)-4。使用补充规则,它将是858993455。
您也可以参考Implicit conversions