C语言之整型提升


1 有可能出现的问题

代码如下

#include <stdio.h>

int main ()
{
  int a = -1;
  unsigned int b = 1;
  if (a < b) {
    printf("a < b");
  } else {
    printf("a >= b");
  }
  
  
  return 0;
}

运行结果
在这里插入图片描述

2 产生以上问题的原因(整型提升)

在表达式计算时,各种整型首先要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型;然后执行表达式的运算。

**为什么要使用整型提升:**表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。简单来说就是为了在计算中有更快的速度。

3 整型提升的过程

1. 有符号整数的整型提升:高位补充符号位

char var1 = -1;

负数在内存中以补码的形式存储,且char类型占一个字节,即8bit

故变量 var1 的二进制补码为1111   1111

整型提升之后,高位补充符号位1int32bit提升后为1111    1111    1111    1111    1111    1111    1111    1111

char var1 = 1;

正数的补码和原码相同,同理可得变量var1的二进制补码为 0000  0001

整型提升之后,高位补充符号位0,提升后为0000    0000    0000    0000    0000    0000    0000    0001

2. 无符号整数的整型提升:高位补0即可

4 整型提升示例

基础知识: 补码的编码规则是:符号位0表示正,1表示负,正数的补码等于原码,负数的补码等于反码末位加1。

#include <stdio.h>

/*
思路:
  a补码:1111  1111
  b补码:1100  0111
  整型提升后(按照32bit):
  a补码:1111  1111    1111  1111    1111  1111    1111  1111   
  b补码:1111  1111    1111  1111    1111  1111    1100  0111
  相加之后  ==  (a + b)补码
         1111  1111    1111  1111    1111  1111    1100  0110
  转化为原码后
         1000  0000    0000  0000    0000  0000    0011  101058
  最终打印的值为 -58
  
 */
int main() {
  char a = -1;
  char b = 199;
  char c = a + b;
  printf("%d", c);
  return 0;
  
}

5 总结

在C语言中,当表达式中包含不及int大小的变量时,编译器会自动将其提升为整型,因此需要特别注意这种情况。