整形提升
1.是什么?
定义:C语言的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
通俗讲:C语言中字节数少于整型字节数的数据类型在进行整型运算时,该类型的数据会被默认转为整型数据。
2.为什么要?
CPU整形运算器(ALU)操作字节长度决定。
表达式的整形运算在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是 int 的字节长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
3.提升规则
将少于4个字节的数据变成4个字节的数据
- 如果是无符号数,则高位直接补0;
- 如果是有符号数,则高位全补符号位。
正数整形提升:高位补充符号位0。负数的整形提升:高位补充符号位1
例如 char c= -1; 10000000 00000000 00000000 00000001 原码
11111111 11111111 11111111 11111110 反码
11111111 11111111 11111111 11111111 补码(-1在内存中的存储形式)
char占1个字节 11111111
有符号数 11111111 11111111 11111111 11111111(整形提升)
4.什么时候进行(整形运算)
注意:char,short等数据在存储是,没有整形提升。发生这个整型提升的前提是它们参与整型运算!而且整型运算结束后,4个字节的数据将发生截断,再返回值。也就是说,运算完成后,CPU返回值的字节数仍为这个数据原本类型的字节数,而不是提升后的字节数。截断的规则是留低位弃高位。
来道题说明一下:
int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if(a==0xb6)
printf("a");
16进制表示
printf("b");
if(c==0xb6000000)
printf("c");
return 0;
}
首先公布结果 c
接下来进行分析:char a = 0xb6;数据赋值发生整形提升吗?no。默念整形运算时发生。
if(a==0xb6)?? 发生,出现了运算。==左边的a是char型,有符号数,发生整形提升
-
if(a==0xb6);
左边的a是char型 00000000 00000000 00000000 10110110(b6内存中的存储形式)
10110110(截断)
11111111 11111111 11111111 10110110 (提升)
16进制表示0xffffffb6
右边的0x6b是字符常量,有符号数, 16进制表示0x000000b6
不相等,故不打印。 -
short b = 0xb600;
左边的b是short型,所以b是有符号数,发生整型提升,b为0xffffb600
右边的0xb6是字面常量,是有符号数,写完整是0x0000b600
不相等 -
if(c==0xb6000000)
c是int,右边4个字节,不需要提升。
来个题瞅瞅
int main()
{
unsigned char a = 200;
unsigned char b = 100;
unsigned char c = 0;
c = a + b;
printf("%d %d",a+b,c);
return 0;
}
-
usigned char 0-255 200,100储存到a和b中发生截断
200在内存 的存储 00000000000000000000000011001000(4个字节) 放到unsigned char a里面 11001000 (截断,一个字节) 100在内存 的存储00000000000000000000000001100100 放到unsigned char b里面 01100100
-
进行计算+时,两个操作数达不到整形大小时,要进行整形提升,unsigned char a,b无符号数进行提升时,高位直接补0即可。
整形提升后的:
00000000000000000000000011001000-a
00000000000000000000000001100100-b
计算 00000000000000000000000100101100-a+b
a+b的结果没有放到c里面去,就没有发生截断,直接以%d的形式打印出来。直接将结果打印出来,300 -
c=a+b %d打印的是有符号数,它看到内存中的c是个char,要整形提升。认为内存中放的是补码,要得到原码打印出来。
c需要将00000000000000000000000100101100-a+b截断成0101100,然后进行整形提升(补0) 00000000000000000000000000101100,经过补码-反码-原码的转换(正数原反补相同),打印 44
参考
1.C语言整型提升的规则及样例详解https://blog.csdn.net/m0_56311933/article/details/119699918
2.整型提升 https://blog.csdn.net/qq_39208237/article/details/109503755