C语言学习--代码分析整形提升过程
Posted 庸人冲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言学习--代码分析整形提升过程相关的知识,希望对你有一定的参考价值。
整型提升
在C语言中,各种整形类型的运算要首先提升为int
类型,再进行计算。如果接收运算结果的变量为short
或者char
则会发生数据截断。
为什么要整形提升
因为表达式在的整形运算实在CPU的运算器内执行,CPU整形运算器(ALU)的操作数字节长度一般与int
的字节长度一样。
因此,表达式中的char
类型和short
类型在运算时会被转换为int
,这种转换称为整型提升。
同时,在整形提升时,一般会提升为signed int
类型,当signed int
装不下时,则会提升为unsigned int
类型。
比如,在C语言中规定了整形的长度 char≤short≤int,如果unsigned short
的长度等于int
,则unsigned short
会被转换为unsigned int
。
整型提升的方式
整型提升是按照变量的数据类型的符号位来提升。
负数的整型提升,高位补符号位1
。
char c1 = -1;
// c1 的二进制补码为:
// 1111 1111
// 整型提升,高位补符号位:
// 1111 1111 1111 1111 1111 1111 1111 1111
正数的整型提升,高位补符号位0
。
char c2 = 1;
// c2 的二进制补码为:
// 0000 0001
// 整型提升,高位补符号位:
// 0000 0000 0000 0000 0000 0000 0000 0001
无符号数整型提升,高位补0
//无符号整形提升,高位补0
unsigned char c3 = 1;
// c2 的二进制补码为:
// 0000 0001
// 整型提升,高位补符号位:
// 0000 0000 0000 0000 0000 0000 0000 0001
代码分析
例1
int main()
{
char a = 3;
char b = 127;
char c = a + b;
printf("%d\\n",c); // -126
return 0;
// b 和 c 运算过程中先被提升为int类型,然后再执行加法运算。
// 加法运算完成后,结果将被截断,然后再存储于a中。
// a + b = 130,对应2进制表示为:
// 0000 0000 0000 0000 0000 0000 1000 0010
// 将值赋值给c,会将溢出的部分截断,得到结果:
// 1000 0010
// char 默认是 signed char ,最高位是符号位,所以此时的c 是负数,并且得到的是补码。
// 以%d格式打印整型,因此c又需要整型提升
// 补码 1111 1111 1111 1111 1111 1111 1000 0010
// 反码 1111 1111 1111 1111 1111 1111 1000 0001
// 原码 1000 0000 0000 0000 0000 0000 1111 1110
// 结果 == -126
}
例2
// 下面代码的执行结果是?
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;
}
逐步分析
-
首先
a
,b
,c
在被赋值时,=
后面的值默认为signed int
类型;所以,
0xb6 == 182 == 0000 0000 0000 0000 0000 0000 1011 0110
a
是signed char
类型,只有8位,最高位为符号位,因此a
在接收值时要发生数据截断;得到:
1011 0110
,此时的值最高位为1是一个负数值,并且是一个补码,我们将其变成原码;a补
1011 0110
a反1011 0101
a原1100 1010
所以
a == -74
-
b
在被赋值时同理:0xb600
==46592
==0000 0000 0000 0000 1011 0110 0000 0000
截断:
b补
1011 0110 0000 0000
b反
1011 0101 1111 1111
b原
1100 1010 0000 0000
-
0xb6000000 == 3053453312 == 01011 0110 0000 0000 0000 0000 0000 0000
因为是有符号数,但是
int
类型又没有空间装下这个最高位的0因此发生截断,最高位
0
被丢弃,1
作为符号位,此时的值为负数,得到:c补
1011 0110 0000 0000 0000 0000 0000 0000
c反
1011 0101 1111 1111 1111 1111 1111 1111
c原
1100 1010 0000 0000 0000 0000 0000 0000
所以在截断后:
0xb6000000 --> -1241513984 == 1011 0110 0000 0000 0000 0000 0000 0000 (补)
而
c
同样是unsigned int
, 刚好可以放下这32位二进制数,所以:c == -1241513984 == 1011 0110 0000 0000 0000 0000 0000 0000 (补)
这里就可以发现
c
和0xb6000000
是相同的。
-
当算出 a == -74, b == -18944, c == -1241513984后,继续进行条件判断,在if() 判断时,两边a,b 要被整形提示。
if (a == 0xb6)
判断的是:a补
-- 1111 1111 1111 1111 1111 1111 1011 0110
(a被整形提升)0xb6 -- 0000 0000 0000 0000 0000 0000 1011 0110
可以看到
(a == 0xb6) == false
-
if(b == 0xb600)
判断的是:b补
-- 1111 1111 1111 1111 1011 0110 0000 0000
(b被整形提升)0xb600 -- 0000 0000 0000 0000 1011 0110 0000 0000
可以看到
(b == 0xb600) == false
-
if(c == 0xb6000000)
判断的是:c补
-- 1011 0110 0000 0000 0000 0000 0000 0000
(c本身就是int
类型)0xb6000000 -- 1011 0110 0000 0000 0000 0000 0000 0000
可以看到
(b == 0xb600) == true
因此,第三个if(c == 0xb6000000)被执行,打印输出a。
以上是关于C语言学习--代码分析整形提升过程的主要内容,如果未能解决你的问题,请参考以下文章