Cprogramming 简明教程

Integer Promotions in C

@ {s20} 为了在整数的 @ {s22} 中实现一致性,将某些 @ {s21} 提升到了更高的等级。

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

Integer Promotions

作为一般原则,当对 @ {s23} 类型进行运算时,小于 @ {s24} 的类型会被提升。如果原始类型的所有值都可以表示为 int,则较小类型的值将转换为 @ {s25};否则,将转换为 @ {s26}。

必须理解 @ {s27} 的概念才能编写可靠的 C 代码,并避免与数据类型大小和较小整数类型的算术运算有关的意外问题。

Example

在这个示例中,两个 @ {s30} @ {s28} 和 @ {s29} 似乎存储相同的值,但它们不相等。

#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 为 -5 的有符号 char,而“b”是已转换为 int 为 251 的无符号 char。

Example: Mechanism of Integer Promotions

让我们尝试使用此示例了解整数提升的机制:

#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

When Integer Promotion is Applied?

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

C 编译器在处理涉及 char 等小型类型的算术运算时应用 @ {s31}。在乘以这些 char 类型之前,编译器将它们更改为 int 类型。因此,在这种情况下,(a * b)将转换为可以容纳乘积结果的 int,即 1200。

Example

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

#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)。

Example

在这个例子中,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: ╚

Integer Promotion Rules

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

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

  1. C 的整型是 char、short、int、long、long long 和枚举。布尔在类型提升时也被视为一种整型。

  2. 没有两个有符号整数类型具有相同的等级,即使它们具有相同的表示。

  3. 有符号整数类型的等级应大于精度较低的有符号整数类型的等级。

  4. long int 的等级 > int 的等级 > short int 的等级 > 有符号 char 的等级。

  5. char 的等级等于有符号 char 和无符号 char 的等级。

  6. 每当在表达式中使用小的整型时,它都会被隐式转换为总是为带符号的 int。

  7. 当在大多数表达式中使用时,所有小的整型,无论其符号如何,都会被隐式转换为(带符号)int。

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

  1. Byte and short values − 提升为 int。

  2. If one operand is a long − 整个表达式提升为长整数。

  3. If one operand is a float − 整个表达式提升为 float。

  4. If any of the operands is double − 结果提升为 double。

Example

这里,变量 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