算术转换与整形提升
程序员文章站
2024-03-18 11:04:52
...
int main()
{
char u = 128;
unsigned char s = 128;
unsigned short us;
us = s + u;
printf("us = 0x%x\n", us);
us = (unsigned char)u + s;
printf("us = 0x%x\n", us);
us = (char)s + u;
printf("us = 0x%x\n", us);
return 0;
}
算术转换
C语言在处理不同类型数值之间的运算时是有一定的规律的。需要先将两个操作数转换为相同的类型才能进行运算。而类型的转换的规律如下图:
- 这里的转换是自动由低向高发生的(当然,强制类型转换是根据用户意愿进行的)。例如:int和unsigned int进行运算,编译器会将低级别的int转换为unsigned int再进行计算。而这个转换编译器并没有对它在内存中的值做出改变,而是使用了不同的读取方式,编译器将原本的int的符号位也当成数值大小进行读取。
- 而这里没有提到的char和unsigned char,short和unsigned short类型在运算时都会自动为‘升级’为int型再进行运算。也就是整形提升
整形提升
相应的,不同的低级别的类型向高级别类型整形提升的过程也是不太一样的。
这里的转换的规律是:
unsigned char在转化时,编译器会将他们当成正数进行转化,在高位补0,补全后就是它的补码
signed char转化时,编译器则会根据他们的正负将他们的高位全部补0或补1,补全后就是它的补码
了解清楚概念后,在来看原题:
char u = 128;
unsigned char s = 128;
unsigned short us;
us = s + u;
printf("us = 0x%x\n", us);
-
128
的补码是00000000 00000000 00000000 10000000
-
u是signed char型(-128–127)的,将
128
放到u时截断,u为10000000
,即-128
。同理,unsigned char型(0–255)的s为128
。 - 当进行s+u算数运行时,先进行整形提升。此时u为
-128
负数,所以前32位补1,即11111111 11111111 11111111 10000000
;s为128
正数,所以前32补0,即00000000 00000000 00000000 10000000
。 - 将s和u的值相加得
00000000 00000000 00000000 10000000 //s的补码 无符号相当于正数,原反补一样,提升为整型时,高位补0,
11111111 11111111 11111111 10000000 //u提升为整型的补码 u是signed char
+ -----------------------------------
[1]00000000 00000000 00000000 00000000
又因为us为unsigned short型,进行截断,即00000000 00000000
,故us=0
。
us = (char)s + u;
printf("us = 0x%x\n", us);
将s强转换成char型,s为10000000
,即-128
;与u相加先整形提升,即
11111111 11111111 11111111 10000000 //u提升为整型的补码 u是signed char
11111111 11111111 11111111 10000000 //s被强制类型转换后,与u有了相同的待遇
+ -----------------------------------
[1]11111111 11111111 11111111 00000000
在进行截断赋值给us,即11111111 00000000,为ff00
us = (unsigned char)u + s;
printf("us = 0x%x\n", us);
同理,就不阐述了,算出来us为0000000100000000,即100;
程序最后验证结果:
上一篇: 数组实现队列
下一篇: Linux安装Docker容器