一.什么是整形提升
整形提升是指将一个或多个操作数的类型提升为另一个更高精度的类型。在表达式中,如果有某个操作数的类型比另一个操作数类型低,则会发生整形提升。整形提升可以防止数据类型的截断和损失,并确保运算结果正确。例如,在C语言中,当执行int类型变量和char类型变量的运算时,char类型变量会被自动转换为int类型,以达到更高的精度。
二.整形提升的规则
表达式的整形运算要在CPU的相应运算器内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。(注意哈,对于char和short类型的运算时,由于它们的长度小于int长度的整形值,所以运算时需要将其转化为int或者unsigned int类型后才可以送到运算器中计算。)
用自己的话来说,就是通过牺牲空间,保证精度的准确,方便计算。
但是哈,并非都转换为int类型,如果遇到double或者float那就不以int为标准了,这就涉及了算术转化。
三.走进整形提升
1.CPU整形运算中都是将其转化为补码进行计算的,为什么呢?
首先呢计算机CPU计算数据时只支持加法计算,使用原码直接相加无法求得正确数值。
因此为了方便计算,计算机中的加法计算是使用补码加法来实现。
我用两个算术让大家更好的理解
int a=1
//原码 00000000 00000000 00000000 00000001
//补码 00000000 00000000 00000000 00000001
int b=-1
//原码 10000000 00000000 00000000 00000001
//补码 11111111 11111111 11111111 11111111
分别以两种形式给大家展示1+(-1)
原码相加 10000000 00000000 00000000 00000010 //结果为-2
补码相加 1 00000000 00000000 00000000 00000000 //溢出位舍去,结果为0
很明显,对于有负数参加的加法运算,使用原码无法得到正确的答案,这就凸显出补码的好处
我再给大家举一个例子 5+(-4)
int a=5 //补码 00000000 00000000 00000000 00000101
int b=-4 //补码 11111111 11111111 11111111 11111100
a+b //补码 1 00000000 00000000 00000000 00000001(溢出位舍去,得到1)
在此就不举原码相加的结果了,有兴趣的小伙伴可以下去就行计算
总而言之,对于有符号数,内存要区分符号位和数值位,要是能把符号位和数值位等同起来,让它们一起参与运算,不再加以区分,只用加法器就可以同时实现加法和减法运算,这样硬件电路就变得简单了。
用自己的或来说,方便计算机的运算,简化计算机硬件的复杂程度
2.到底如何进行整形提升?
咳咳,废话有点多,让我们进入今天的正题
对于数据类型等进行整形提升时,要分清楚是有符号位还是没有符号位!!!!!
重要的事情打四个感叹号,因为两者的整形提升时的原则并不相同,鄙人再校面试中混淆,乱答了一大堆,有前车之鉴的,呜呜呜。
有符号位的整形提升:
1.负数:高位补充符号位,即高位全部补1
2.正数:高位补充符号位,即高位全部补0
对于无符号为的整形提升:
无论最高位是啥,就算是天王老子来了,也全部补0(嘿嘿嘿,调皮一下)
3.以代码运行的形式让大家看看整形提升的实际运用:
#include<stdio.h>
int main()
{
//当前的char都是有符号类型
char a = 1;
char b = 128;
char c = a + b;
printf("%d", c);
return 0;
}
大家可以猜一下结果,是不是有的小伙伴会认为结果为129,但结果可能会很奇妙,答案为-127
很震惊吧,接下来让我们仔细讨论讨论
#include<stdio.h>
int main()
{
//当前的char都是有符号类型
char a = 1;
//a的补码 00000001
//整形提升后结果为 00000000 00000000 00000000 00000001
char b = 128;
//b的补码 1000 0000
//整形提升的结果为 11111111 11111111 11111111 10000000
char c = a + b;
//相加后的结果为 11111111 11111111 11111111 10000001
//截断后的结果为 10000001
printf("%d", c);
//由于%d的形式打印会整形提升 11111111 11111111 11111111 10000001
//打印的结果就为-127
return 0;
}
有些小伙伴可能会问为什么会有截断呢,别忘了,char类型只有8个比特位
4.为了让大家直观的感受整形提升可以看如下代码
int main()
{
char a = 1;
printf("%d", sizeof(a)); //1
printf("%d", sizeof(+a)); //4
printf("%d", sizeof(-a)); //4
return 0;
}
对于a的加减运算时,系统就已经将char类型的转化为int类型的处理了
5.现在讨论一下无符号类型的
int main()
{
char a = -128;
printf("%u", a); //结果4294967168
return 0;
}
为啥这个值会这么大里?让我们分析分析:
int main()
{
char a = -128;
//a的补码 100000000
printf("%u", a);
//由于是char为有符号数据,整形提升后为
//11111111 11111111 11111111 10000000
//该输出为无符号整形
//故输出为11111111 11111111 11111111 10000000对应的十进制
return 0;
}
然后就可以掏出我们的计算器了
发现符合结果的,有时就是这么神奇,哈哈哈
6.让我们看最后一个举例
int main()
{
unsigned char a = -1;
//补码 11111111
printf("%u", a); //255
//进行整型提升时为
//00000000 00000000 00000000 11111111
//对应的十进制就为255
return 0;
}
注意哈,a的类型是unsigned char类型,以无符号类型打印时就是这样的
四:结束语
我也是刚入坑的小白,该文章如果有如何问题欢迎在评论区及时指出错误,谢谢大家耐心阅读!!!!
隐墨想要告诉大家的是,目前哈我们学习的是c语言的语法,但为什么要这样规定呢?有着很深的学问,这就要感叹发明计算机的伟人了,真的很厉害,我们要坚持学下去,到后边你就会发现这个东西很神奇哈!愿与诸君共勉!