变量的整型提升和截断
什么是整型提升?
在 CPU 运算时,为了方便 CPU 的运算,(一般情况下)把字节长度不足
int
类型长度的变量类型(例如:cahr
short
)先转换为至少为int
类型的类型长度进行计算,这个过程叫做 整型提升
什么是截断
截断是指当将较大类型的数据存储到较小的数据类型变量中时,多余的位会被去掉,导致信息丢失。
接下来我将用一个简单的小程序,同时说明整型提升和截断之间的关联
因为截断时需要判断最高位是 0 还是 1,以便来判断一个变量的正负
所以首先要说明一些别的东西:
什么是原码、反码和补码
例如现在有一个十进制数 10 吧,把它转换成 8 位的二进制编码,
也就是:0000 1010
它就是一个原码:0000 1010
反码就是把这 8 位二进制编码按位取反
也就是: 1111 0101
而一个原码的补码就是原码的反码 + 1
也就是: 1111 0110
知道了原码、反码和补码,这个时候就可以告诉你,变量在程序里储存的时候,正数用的是原码,负数用的是补码,最高位是符号位(0正 1负)
例如:
char a = 10;
char b = -10;
char
在内存中占的是一个字节,也就是 8 位,
此时a
在内存中用二进制表示为: 0000 1010
此时b
在内存中用二进制表示为: 1111 0110 (这个位置用了原码转补码的规则)
也就是说如果这个例子中的 a
和 b
相加,假如它的最高位是 1 ,那么它里面放的就是负数,运用的就是补码的规则,而补码想要得到原码就需要这样
现在有一个补码是 : 1111 0110
我先让它-1
得到它原码的反码: 1111 0101
在对它取反就可以得到它的原码了:0000 1010
聪明的小伙伴可能已经发现了这就是-10
推导到10
的过程,而上面的例子是从10
推导到-10
的过程
知道了如何判断一个变量用的是原码还是补码就可以判断出一个被截断的变量的值。
变量的整型提升高位补的是符号位,也就是说:
char a = 10;
char b = -10;
int c = a + b;//这个时候由于a
和b
的长度都不足int
类型的长度,这里发生了整型提升
a
没有整型提升前 在内存中用二进制表示为: 0000 1010
b
没有整型提升前在内存中用二进制表示为: 1111 0110由于整型提升高位补符号位
此时
a
在内存中二进制表示为:
00000000 00000000 00000000 00001010
此时b
在内存中二进制表示为:
11111111 11111111 11111111 11110110
好下面例子来了
示例 :
#include <stdio.h>
int main()
{
char a = 127;
// 127 的二进制编码 0111 1111
char b = 3;
// 3 的二进制编码 0000 0011
char c = a + b;//把 a + b 的值赋给 c
//char 类型不满足 int 类型的长度,整型提升得出
// 127
//0000 0000 0000 0000 0000 0000 0111 1111
// 3
//0000 0000 0000 0000 0000 0000 0000 0011
// 故 a + b 的值为
//0000 0000 0000 0000 0000 0000 1000 0010
//这里以为 c 是 char 类型的变量,所以发生了截断 c,取低八位也就是 1000 0010
//取完低八位后,截断之后的值是 1000 0010,注意这里的最高位是 1,也就是说它是一个负数
//它服从补码的规则
//1000 0010 ->补码
//1000 0001 ->反码
//0111 1110 ->原码 126
//所以这个是有符号的 126
//即 -126
printf("%d", c);
return 0;
}
运行结果
跟上面注释分析的是一样的