一、unsigned int变量跟int类型的变量运算时得出的结果是什么类型的?
1、先看一个有趣的例子:
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位机下)(最高位是符号位),补码也就是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。
有趣的例子2:
int a = -6;
unsigned int b = 3;
if((a+b)>20)
{
printf("yes\n");
}
else
{
printf("no\n");
}
return 0;
运行结果:
yes
(3)代码分析:
按照刚刚的分析,a+b会隐式转换成为unsigned int类型,a转换成为unsigned int类型以后也就是-6的补码直接转换,为65530(32位机下)。b本身为unsigned int,也就是3,所以a+b=65533(32位机下),所以输出yes。
二、总结
①当一个int类型的a与unsigned int类型的b相运算时,例如:a+b的时候,如果直接是a+b的话,各个变量就会隐式转换成为unsigned int的类型再相加。
②当用print函数指定打印的时候,例如:printf(”%d\n”,a+b),就要各个变量转换为%d的类型再想加。
③当用一个int c类型去装这个结果时,如:c=a+b,同理,a和b会根据c的类型去分别转换跟c一致的类型再去运算。