整型提升是什么:
✈性质:
"整型提升" 是C语言程序设计中的一项规定。即——在进行表达式计算时,先将涉及的相关整型转换(提升)成int(整型)类型 或 unsigned int(无符号整型)类型。
为什么会有整型提升:
📉原因:
整型运算要在CPU内的运算器件执行,CPU中整型运算器(ALU)的操作数的字节长度一般就是int的字节长度(4字 节),同时也是CPU的通用寄存器的长度。因此,即使两个char类型(1字节)的数相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度4字节之后才执行运算操作。
整型提升的规则:
若变量类型为unsigned(无符号)类型,则在内存中存储的二进制补码前添‘0’,直至补齐32位。
若变量类型为signed类型,则在内存中存储的二进制补码前添该二进制补码的最高位(不一定是符号位),直至补齐32位。
即——遵循什么提升规则是看变量本身的类型,而不是输出类型
整型提升的实际运用:
📂例1:
#include<stdio.h>
int main()
{
unsigned char a = 200;
unsigned char b = 100;
unsigned char c;
c = a + b;
printf("%d\n",a+b);
printf("%d\n",c);
return 0;
}
🎅分析:
首先写出 a 和 b的值在内存中存储的二进制补码,由于是正数,原码 反码 补码相同。
内存中:
00000000 00000000 00000000 11001000 --- 200
00000000 00000000 00000000 01100100 --- 100
变量类型中:
11001000 --- a
01100100 --- b
a + b 是计算过程,直接对a和b的二进制补码执行运算操作,存储在内存中,内存有32位,所以a+b的二进制补码有32位
c 存储的是a+b的计算结果,但该结果不是存储在内存中,而是存储在已经声明了类型的变量(即unsigned char c)中,即c的二进制补码只有8位存储空间,只存储 a+b 的二进制补码结果的前8位,高位舍弃
因此可以认为二者的二进制补码存储格式分别为
00000000 00000000 00000001 00101100 ——> a+b
-------- -------- -------- 00101100 ——> c (只有8位)
存储后的二进制数都是补码!
变量a,b,c是unsigned char类型,而输出是整型
!!当变量类型和输出类型不同时,要对变量进行整型提升
如何进行整型提升规则要看该变量在定义时的类型是否是unsigned类型:
若是unsigned型,则求得的补码等于原码,直接输出
若不是,则要将求得的补码转换成原码再输出
因为a+b都是unsigned char 型,故整型提升时在最高位前补‘0’ 且unsigned类型求得补码即原码:
00000000 00000000 00000001 00101100 ——> a+b
故unsigned char (a+b)以%d形式输出值为300
——————————————————————————————————————————
因为 c 是unsigned char 型,故整型提升时在最高位前补‘0’ 且unsigned类型求得补码即原码:
00000000 00000000 00000000 00101100 ——> c (补齐32位)
故unsigned char c以%d形式输出值为 44
📂例2:
int main()
{
char a = 128;
printf("%u\n", a);
printf("%d\n", a);
//分析:
//00000000 00000000 00000001 00000000 char128
//11111111 11111111 11111111 00000000 提升后
//
//%u:
//11111111 11111111 11111111 00000000
//输出———— 4294967168
//%d:
//11111111 11111111 11111111 00000000 补码
//11111111 11111111 11111110 11111111 反码 == 补码-1
//10000000 00000000 00000001 00000000 原码 == (对反码进行取反)
//输出—— -128
return 0;
}
📂例3:
#include<stdio.h>
int main()
{
unsigned char b = 200;
printf("%d\n",b);
printf("%u\n",b);
//分析:
//00000000 00000000 00000000 11001000 200
// 11001000 b
//00000000 00000000 00000000 11001000 unsigned char b正数
// 以%d %u输出的补码均是原码,输出都是200
return 0;
}
📂例4:
#include<stdio.h>
int main()
{
signed char c = 200;
printf("%d\n", c);
printf("%u\n", c);
//分析:
//00000000 00000000 00000000 11001000 200
// 11001000 c
//11111111 11111111 11111111 11001000 提升后:signed char c 补码
//
// %d :> 将最高位看作符号位,补码为负,要转换
//11111111 11111111 11111111 11001000 补
//11111111 11111111 11111111 11000111 反
//10000000 00000000 00000000 00111000 原
// 输出:-56
//
//
// %u :> 将最高位看作数值位,则补码等于原码
// 11111111 11111111 11111111 11001000 即为原码
// 输出:4294967240
return 0;
}
总结:
发生整型提升的简略过程:
首先写出对应变量的‘值’的二进制补码,
然后根据变量在定义时的类型,截取对应类型的字节长度的二进制补码
再看变量类型是否是unsigned型,是则在截取后的值的最高位前补‘0’,至补齐32位;不是则用截取后的值的最高位补齐32位。补齐后求得待输出的值的补码
最后根据输出类型判断求得的补码的最高位是符号位还是数值位,转换成原码后输出
“求值”——“截取”——“提升”——“输出”