C 语言中的整数提升



为了在整数的算术运算中保持一致性,C 编译器会将某些数据类型提升到更高的级别。

除了标准的 int 数据类型之外,C 语言还允许您使用其子类型,例如 char、short int、long int 等。这些数据类型分别占用不同的内存空间。例如,标准 int 的大小为 4 字节,而 char 类型的大小为 2 字节。当算术运算涉及长度不等的整数数据类型时,编译器会采用整数提升策略。

整数提升

作为一般原则,小于 int整数类型在对其执行运算时会被提升。如果原始类型的所有值都可以在 int 中表示,则较小类型的值将转换为int;否则,它将转换为unsigned int

必须理解整数提升的概念才能编写可靠的 C 代码,并避免与数据类型大小和对较小整数类型进行算术运算相关的意外问题。

示例

在此示例中,两个变量ab 似乎存储了相同的值,但它们并不相等。

#include <stdio.h>

int main(){

   char a = 251;
   unsigned char b = a;

   printf("a = %c", a);
   printf("\nb = %c", b);

   if (a == b)
      printf("\n Same");
   else
      printf("\n Not Same");
   
   return 0;
}

输出

运行此代码时,将产生以下输出:

a = √
b = √
Not Same

您得到此输出是因为“a”和“b”在比较期间被视为整数。“a”是转换为 int 的有符号 char,值为 -5,而“b”是转换为 int 的无符号 char,值为 251。

示例:整数提升机制

让我们尝试通过此示例来了解整数提升的机制:

#include <stdio.h>

int main(){
   
   char a = 'e', b = '2', c = 'M';
   char d = (a * b) / c;
   
   printf("d as int: %d as char: %c", d, d);
   
   return 0;
}

输出

运行代码并检查其输出:

d as int: 65 as char: A

何时应用整数提升?

在算术表达式“(a * b) / c”中,首先解决括号。所有变量都为有符号 char 类型,长度为 2 字节,可以存储 -128 到 127 之间的整数。因此,乘法超出了 char 的范围,但编译器不会报告任何错误。

当 C 编译器处理涉及 char 等小型类型的算术运算时,会应用整数提升。在这些 char 类型相乘之前,编译器会将其更改为 int 类型。因此,在这种情况下,(a * b) 转换为 int,它可以容纳乘法的结果,即 1200。

示例

整数提升作为通常的算术转换的一部分应用于某些参数表达式;一元 +、- 和 ~ 运算符的操作数;以及移位运算符的操作数。请查看以下示例:

#include <stdio.h>

int main(){

   char a = 10;
   int b = a >> 3;

   printf("b as int: %d as char: %c", b, b);

   return 0;
}

输出

运行此代码时,将产生以下输出:

b as int: 1 as char: 

在上面的示例中,将“a”的位结构向左移动三位仍然导致其值在 char 的范围内(a << 3 的结果为 80)。

示例

在此示例中,char 变量的等级被提升为 int,以便其左移操作超出 char 类型的范围。

#include <stdio.h>

int main(){

   char a = 50;
   int b = a << 2;
   
   printf ("b as int: %d as char: %c", b, b);
   
   return 0;
}

输出

运行代码并检查其输出:

b as int: 200 as char: ╚

整数提升规则

提升规则帮助 C 编译器保持一致性并避免意外结果。提升规则背后的基本原则是确保表达式的类型调整为容纳所涉及的最宽数据类型,从而防止数据丢失或截断。

以下是根据 C11 规范的提升规则摘要:

  • C 语言中的整数类型有 char、short、int、long、long long 和 enum。在进行类型提升时,布尔值也被视为整数类型。

  • 任何两个有符号整数类型都不应具有相同的等级,即使它们具有相同的表示形式。

  • 有符号整数类型的等级应大于任何精度较低的有符号整数类型的等级。

  • long int 的等级 > int 的等级 > short int 的等级 > signed char 的等级。

  • char 的等级等于 signed char 和 unsigned char 的等级。

  • 每当在表达式中使用小型整数类型时,它都会隐式转换为 int,int 始终是有符号的。

  • 所有小型整数类型,无论符号如何,在大多数表达式中使用时都会隐式转换为(有符号)int。

简而言之,我们有以下整数提升规则:

  • 字节和短整数值 - 它们被提升为 int。

  • 如果一个操作数为 long - 整个表达式被提升为 long。

  • 如果一个操作数为 float - 整个表达式被提升为 float。

  • 如果任何一个操作数为 double - 结果被提升为 double。

示例

这里,变量xy 为 char 数据类型。当对它们执行除法运算时,它们会自动提升为 int,结果值存储在z 中。

#include <stdio.h> 

int main(){
 
   char x = 68;
   char y = 34;
    
   printf("The value of x is: %d", x);
   printf("\nThe value of y is: %d", y);
    
   char z = x/y;
   printf("\nThe value of z: %d", z);
    
   return 0; 
}

输出

运行此代码时,将产生以下输出:

The value of x is: 68
The value of y is: 34
The value of z: 2
广告