作者主页:@Fire_Cloud_1
学习社区:烈火神盾
专栏链接:C生万物
有关隐式类型转换中的整型提升,相信对于很多读者来说比较神秘,但若是了解了这一块的小知识便可以很好地解开你对很多类型转换的一些困惑,清楚数据在内存中是如何发生变化的
为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换为普通整型,这种转换称为[整型提升]
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。
通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int
或unsigned int
,然后才能送入CPU去执行运算
通过上面的陈述,相信你对整型提升有了一个初步的概念,接下去我们来看看如何去进行一个整型提升
对于整型提升来说,整数和负数是不一样的,首先我们来看看正数的整型提升
//正数的整形提升
char c1 = 1;
1
的32个二进制位00000000000000000000000000000001
,然后将其转换为原码的形式,但是通过上面的学习我们可以知道对正数的原、反、补码是相同的,因此这就是它在内存中的形式00000001
填充24个符号位
,以达到整型4个字节32个比特位在内存中的要求,那么此时提升之后的结果便是00000000000000000000000000000001
可以看出又回到了原来的1,不过若是你不去使用这个c1的话是不需要进行整型提升的接下去再来看看负数的整型提升
//负数的整形提升
char c2 = -1;
11111111111111111111111111111111
。同理,将其给到一个整型的变量之后就会发生截断即为11111111
好,说完了该如何去进行整型提升之后我们就可以去代码段中看看到底是如何进行的
首先来看第一个,我们要去计算两个整数的和,但是呢却要放到char类型的变量中去,那会发生什么化学反应呢
int main(void)
{
char a = 5;
char b = 126;
char c = a + b;
}
00000000000000000000000000000101 - 5
——> 00000101 - 5【截断】
00000000000000000000000001111110 - 126
——> 01111110 - 126【截断】
[整型提升]
,在高位补充24个符号位之后就变成了下面这样,然后便可以对它们去进行一个运算了//到了内存中开始计算 —— 整型提升(正数)
00000000000000000000000000000101 - 5
00000000000000000000000001111110 - 126
5 + 126 = 131
%d
做一个打印,那么此时就会输出正确的内容13100000000000000000000000010000011 - 131
10000011 - 131【截断】
可是呢,我就是不用整型去接收,就是玩用字符型去接受,然后再用%d
去打印(“主要还是为了加深知识点的灵活运用”)
printf("c的整数打印形式为:%d\n", c);
printf()
库函数其实也算是一个运算,也要放到内存里面去,然后这个变量c又不是整型,所以此时呢就又会发生一个[整型提升]
了10000011
前面的24个符号位了//整型提升(负数)
11111111111111111111111110000011 - 补码
11111111111111111111111110000010 - 反码
10000000000000000000000001111101 - 原码
-125
,我们来看看结果【全体起立】接下去再来看看第二个栗子
10110110
,那其实到这里我就已经可以看出答案是多少了,只有最后一个if语句会进去,其余的都不成立int main()
{
char a = 0xb6;
short b = 0xb600;
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c");
return 0;
}
十六进制的b
,因为它的二进制为1011
,可以看到首位是为1,那么当这个变量a参与运算的时候就会发生一个[整型提升]
,在上面我说到过对于负数的整型提升和正数不一样,填充符号位后均为1,那么再转化为原码从计算机输出之后就一定不会是原来的值了,会发生一个改变char a
和short b
它们均不是一个整型int类型的数据,所以都会发生一个[整型提升]
,不过int c
它就是一个整型的变量,所以是不会发生变化的通过这个例子相信你对整型提升一定有了更加深刻的理解
最后一个小案例我们和sizeof做一个结合,顺便再回顾一下前面的知识点
int main()
{
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(c + 1));
printf("%u\n", sizeof(+c));
printf("%u\n", sizeof(-c));
return 0;
}
sizeof(c)
很明确,计算的就是char这个数据类型的字节长度,也就是1,可以对于下三个结果为什么会发生整型提升呢?我们来分析一下c + 1
来说它是一个表达式,上面说到过若是一个char类型或者是short类型定义的变量参与了运算,那在内存中就会发生一个整型提升,那如果这是一个表达式的话也就相当于是参与了运算,整型提升后变为4个字节,具体细节不做展开+c
和-c
来说就是我们前面说到过的单目操作符中的+
和-
操作符,和一个操作数结合也可以说它是一个表达式,那么同理也会进行一个整型提升但是我再将它们变个形却又不会发生【整型提升】了,一起来看看
char c = 1;
printf("%u\n", sizeof(c + 1));
printf("%u\n", sizeof(+c));
printf("-------------------\n");
printf("%u\n", sizeof(c = c + 1));
printf("%u\n", sizeof(++c));
c + 1
改换成了c = c + 1
,就不会发生整型提升了,这是为什么呢?因为对于c + 1这个表达式来说确实会发生整型提升,但是呢我又将这个表达式计算后的结果放到c里面去,还记得我在讲述sizeof()里的时候说到它里面的表达式是不会运算的吗,所以整个表达式的结果其实就是sizeof(c)
的结果,和上面所列出的第一个是一样的++c
,那又有同学会产生疑惑,为何+c
会发生整型提升,但是++c
却不会呢,其实对于++c
来说就等价于c = c + 1
,那其没有发生整型提升的原因相信你已经清楚了以上就是有关【整型提升】要介绍的所有内容,看完这些相信你对计算机内部隐式类型转换一定有了一个深刻的了解
好,我们来总结一下本文所学习的有关【整型提升】的内容
整型提升
的意义所在是为了让CPU中的【算术逻辑运算单元ALU】获得一个整型操作数的标准长度,以此来达到更好的计算整型提升
[整型提升]
的作用,揭开了它的神秘面纱文章到这里就结束了,近期遇到了有关【整型提升】的内容,特此总结做个分享
2023年1月3日记