参考:语言中文网
和https://blog.youkuaiyun.com/gyyu32g/article/details/79089475
一、C语言的int类型与unsigned int运算的问题
1、signed int 可以简写成int ,unsigned int 一般不做简写。
2、在不同类型的混合运算中,编译器也会自动地转换数据类型,将参与运算的所有数据先转换为同一种类型,然后再进行计算。转换的规则如下:
(1)转换按数据长度增加的方向进行,以保证数值不失真,或者精度不降低。例如,int 和 long 参与运算时,先把 int 类型的数据转成 long 类型后再进行运算。
(2)所有的浮点运算都是以双精度进行的,即使运算中只有 float 类型,也要先转换为 double 类型,才能进行运算。
(3)char 和 short 参与运算时,必须先转换成 int 类型。
下图对这种转换规则进行了更加形象地描述:
二、实际例子:
int main()
{
int a = 3;
unsigned int b = -6;
printf("%d\n", a+b);
if((a+b)>0)
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
}
运行结果:
-3
yes
看到这个运行结果,很多小伙伴开始疑惑了?unsigned int类型怎么可以赋值一个-6?既然打印出来结果是-3<0,为什么还打印出来是yes?有这些问题的小伙伴且听我娓娓道来。
(1)必须知道的是:
①int类型和unsigned int类型的差别。unsigned int类型比int类型的容量大是因为,unsigned int是无符号类型的,所以最高位不表示正负,而int类型的最高位是表示正负的,1表示负数,0表示正数。
②在计算机中,负数存储的方式都是以其其补码形式储存。
例如:6在计算机的存储形式是0000 0000 0000 0110(32位计算机中),而-6是1000 0000 0000 0110 (32位机下)(最高位是符号位,这里为1,表示负数),补码也就是1111 1111 1111 1010(32位计算机中),补码=原码取反+1。
③赋值一个负数给unsigned int类型的变量,它的意思就是将-6这个数的补码形式(1111 1111 1111 1010(32位机下))形式存到一个叫b的空间中,下次我读取这个数的时候,是使用b这个名字,按照b这个名字的类型来读取的,所以当b是unsigned int类型的时候,就不考虑最高位是符号位,则b = 1111 1111 1111 1010(32位机下)(因为是无符号),当b是int类型的时候,考虑最高位是符号位(1为负数,0为正数),当发现是1的时候也就是负数的时候,计算机会把它转换成为原码从而读出是-6。所以一个变量的类型是决定读取这个变量存储的数的方式。
④自动类型转换。当unsigned int类型与int类型运算时,如果没有指出转换的类型,它会进行“隐式转换”转换为unsigned int类型,也可以记住,不同类型进行运算时,没指出转换的类型时,它会往容量大的那总类型转换,因为这样可以更加容易避免溢出嘛。
(2)代码分析:重中之重,本文重点
首先,定义了一个 int a = 3 。a的存储以3的二进制形式存储。 unsigned int b = -6 。b的存储是以其补码存储的,也就是1111 1111 1111 1010(32位机下)。当执行a+b的时候,printf函数要求指定打印出%d,所以,a以int(%d)类型读取出来,也就是3;b也是以int(%d)类型读取出来,也就是-6,所以3+(-6)=-3,发现打印结果是-3。
重点:
而在后面的 if((a+b)>0) 判断中,(a+b)中并没有指定读取的类型,所以就进行隐式转换,a就转成unsigned int类型,也就是3;b转成unsigned int类型,因为b本来的存储是1111 1111 1111 1010(32位机下),**转成unsigned int类型时不考虑符号位,所以就直接以补码的形式转化,**也就是65530(32位机下),所以a+b=65533>0,输出yes。