目录
一 . 整型提升的定义
首先,我们应该知道这一点:C语言中整型运算总是至少以缺省整型类型的精度来进行的。
这句话什么意思呢?用大白话说就是:C语言中字节数少于整型字节数的数据类型在进行整型运算时,该类型的数据会被默认转为整型数据。
其中,该类型的数据被转化为整型数据的过程就称为整型提升。
二 . 为什么会发生整型提升
这是由计算机体系结构决定的,计算机中的计算都由CPU完成,具体来说是由CPU中的运算器(ALU)完成的。而ALU一般在被设计时,其操作对象——操作数的字节大小被要求至少是int的字节数。此时,我们还要明晰一个事情,那就是数据在被运算时,数据并不是直接在ALU上存储的,而是存储在CPU的寄存器(register)中,而通用寄存器的字节大小与ALU操作数的字节大小保持一致。
大字节数据也可以储存小字节的数据。但问题在于大字节数据拥有4个字节的空间,如果时少于4个字节的数据,该将其放置哪些字节里面?如果随便存放,在需要获取其信息时,还需花费时间寻找存放数据的字节,这样势必会使效率变低。所以,在存放时,至少需要将小字节的数据变成4个字节的,这时就发生了整型提升。
在32位平台,C语言非自定义数据类型的字节数只有4种(1,2,4,8)。
非自定义数据类型的字节数取值可能,我们发现只有(1,2)在进行整型运算时,会发生整型提升。而这两个数据类型对应的便是char与short。
总的来说:C语言中,表达式中的字符和短整型操作数在使用之前会发生整形提升,变为普通整型。
三 . 简述数据存储(以“ int ” “ char ”为例)
C语言中,int 类型的数据在内存中存储需要4个字节,也就是32个bite位。
int a = 1;
//x在内存中存储的二进制为00000000 00000000 00000000 00000001
int b = -1;
//x在内存中存储的二进制原码为10000000 00000000 00000000 00000001
// 反码为11111111 11111111 11111111 11111110
// 补码为11111111 11111111 11111111 11111111
unsigned int c = 1;
//x在内存中存储的二进制为00000000 00000000 00000000 00000001
unsigned int d = -1;
//x在内存中存储的二进制原码为10000000 00000000 00000000 00000001
// 反码为11111111 11111111 11111111 11111110
// 补码为11111111 11111111 11111111 11111111
当我们分别给有符号整型a , b 和无符号整型 c , d 储存1和-1时 他们的二进制存储如上面代码块所示
当我们分别打印他们的时候会显示如下
printf("a=%d\n b=%d\n c=%d\n d=%d\n",a,b,c,d);
a=1
b=-1
c=1
d=4294967295
我们发现将-1存储到无符号整型变量里时,补码11111111 11111111 11111111 11111111就会认为是一个无符号的数据,将其打印到屏幕是,按照二进制的计算规则,左边第一位就不再是符号位,而代表一个数据,十进制打印也就会出现 d=4294967295这样的情况。
而有符号的数据类型,左边第一位为1就代表它为负数,为0就代表他为正数。
四 . 简单的整型提升(以“ int ” “ char ”为例)
我们举一个例子,写一段代码,分别将300储存到 int 类型和 char 类型的变量中,并打印到屏幕上。
int a = 300;
char b = 300;
printf("a=%d\n", a);
printf("b=%d\n", b);
我们发现明明都是300,为什么打印出来的值却不一样呢?
因为计算机储存数据时会将其转换为32个二进制位数据进行存储,而 char 类型只能存放一个字节也就是八个bite位的数据,此时就会发生截断现象,也就如上图所示,b变量内存储的只是红色标记部分的00101100,而我们在打印时又是以整型数据打印的,这个时候就会发生整型提升,也就是将char类型的数据通过左补符号位来进行整型提升,此时b打印出来的数值就是44。
五 . 整型提升的规则(以 “ char ”为例)
整型提升分为有符号和无符号两种。
5.1 有符号的:
整型提升时是按照变量的补码被截断时的最高位是什么进行补位的,如果截断后最高位即最左面的一位数为 1 则在最高位前补 1 ,如果最高位是 0 则在前面补 0 ,补够32位即int类型即可。
例如
char a = 128;
char b = 127;
printf("a=%d\n", a);
printf("b=%d\n", b);
在存储时我们只会将红色部分的数据存储到a和b中,当我们使用“%d”来打印时,需要将他们整型提升,也就是按照整型提升的规则进行补位/,如下。
a数据的左一位为1,所以左边用1补足32位,b数据同理。
但因为是有符号类型,所以a会被当作负数进行打印,我们需要通过补码来得到它的原码。
此时a所打印的值就为-128。
5.2 无符号的:
直接在被截断的前面补 0 即可。
同样我们以实例说话。
unsigned char a = 128;
unsigned char b = 127;
printf("a=%u\n", a);
printf("b=%u\n", b);
因为我们的数据类型为无符号类型,所以左边直接用0补足32位即可,打印出来的数值如下图所示。
六 . 结语 :
整型提升时需注意区分有符号无符号的提升方法,储存变量时也要注意是否有截断的发生。
十分感谢您观看我的原创文章。
本文主要用于个人学习和知识分享,学习路漫漫,如有错误,感谢指正。
如需引用,注明地址。