什么是整型提升?
C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
什么叫缺省整数类型?缺省在计算机里面是默认的意思。
这句话大概意思就是,在c语言的整数运算中,如果有精度小于整型的非自定义类型数,就需要先转换为一个整数类型。
比如char和short int类型,它们的字节数分别为1、2,如果它们参与整数表达式的运算就会先转换成整数类型,再参与运算。
这里我们只谈论char和short int
代码举例:
int main()
{char a = 0x80;short b = 0x8000;int c = 0x86000000;if (a == 0x80)printf("a");if (b == 0x8000)printf("b");if (c == 0x86000000)printf("c");return 0;
}
看结果:
只输出了一个c。
为什么会这样呢?a、b变量被赋予的值也没有超出它们的字节大小代表的最大值,为什么a==0x80和b==0x8000会为假呢?
这其中就发生了整型提升。
整型提升的规则
1、操作数为int的时候,高位补充符号位
2、操作数为unsigned int(无符号整数)的时候,高位补充0
分析例子
1.变量a整型提升:
首先,a占一个字节,在转换前被赋值0x80(十六进制),二进制(补码)表示为1000 0000。
符号位是1.
整型提升变成四个字节,前面补充1,就转换成了:
1111 1111 1111 1111 1111 1111 1000 0000
所以这个时候的a就不等于原来的数了,很明显这都变成了一个负数。
2.变量b整型提升:
首先,b占两个字节,在转换前被赋值0x8000(十六进制),二进制(补码)表示为:
1000 0000 0000 0000
符号位是1.
整型提升变成四个字节,前面补充1,就转换成了:
1111 1111 1111 1111 1000 0000 0000 0000
所以这个时候的b就不等于原来的数了,很明显这都变成了一个负数。
而c是int,不需要转换。
代码1:
int main() {char a = 0x80;char b = 0x80;int c = a + b;printf("%d", c);return 0;
}
这里又会输出什么结果呢?
因为运算涉及到整数,所以字符a和b在参与计算的时候会先整数提升,而根据上面我们知道,a整型提升之后是一个负数,所以得到:
代码2:
int main()
{char c = 1;printf("%u\n", sizeof(c));printf("%u\n", sizeof(+c));printf("%u\n", sizeof(-c));return 0;
}
这里我们要注意,我前面已经强调过,只有在参与运算的时候才会考虑是否要整型提升,而sizeof(c)里的c并没有参与运算,所以不需要整型提升,得到的还是一个字节。
那么sizeof(+c)和sizeof(-c)呢?c语言会认为(+c)和(-c)都是参与了运算,所以需要整型提升,得到的也就是一个整型的字节大小。
整型提升的意义?
表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度 一般就是int的字节长度,同时也是CPU的通用寄存器的长度。 因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。 通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。
总的来说,整型提升的目的是为了保持表达式中操作数的一致性。当不同大小的整数类型参与运算时,较小的类型会被提升为较大的类型,以避免精度丢失和数据溢出的问题。