可以先看看下面这段代码,思考输出结果如何?
#include <stdio.h>
int main()
{
signed char a = 127;
signed char b = 127;
signed char c = a + b;
printf("a+b=%d\n", a + b);
printf("a+b=%d\n", c);
printf("sizeof(a+b)=%u\n", sizeof(a + b));
printf("sizeof(c)=%u\n", sizeof(c));
return 0;
}
step1:明确char类型的变量在内存中存储的是ASCII码值,signed char是有符号字符变量,最高位是符号位
step2:
step3:
查看结果:
?问题一:为什么a+b会等于254,a与b都是有符号数,两个有符号数相加得到的结果没有符号位了吗。
?问题二:为什么将a+b的值赋给c以后再进行打印,就是有符号数的形式了。
解答:
问题一:整型提升
表达式的运算是在CPU中相应运算器中进行的,现在的电脑大多使用的是32位及以上结构的CPU。32位结构CPU代表的意思:CPU中的寄存器最大宽度是32(就是最多存32位)、运算器一次最多处理32位数据、寄存器和运算器之间的通路最宽是32位。对于低于32位的数据进行处理会比较麻烦,但也不是不能处理(可以学习汇编语言了解详情)。为了简化问题,就有了整型提升。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。
上面的问题就迎刃而解了。a和b都发生了整型提升,变为了int类型。两个int类型的变量相加结果位int类型。所以结果为:0000 0000 0000 0000 0000 0000 1111 1110(signed int) 最高位为0,表示整数,原反补码相同,十进制为254。
问题二:将a+b的int类型结果截断放入signed char类型变量c里面。c是有符号数,所以1111 1110是负数的补码,换算回原码就是-2。说一嘴:一个变量的数据类型决定以什么角度看待它内存空间存储的数据。
通过后面sizeof()打印大小也能佐证a+b确实发生了整型提升变为了4字节,而c也发生了截断。
题外话:如果想要学习汇编语言的话,强烈推荐王爽老师的《汇编语言》!