C 语言中的整数提升
C 编译器会将某些数据类型提升到更高的级别,以确保整数算术运算的一致性。
除了标准的 int 数据类型外,C 语言还允许您使用其子类型,例如 char、short int、long int 等。每种数据类型占用的内存空间大小不同。例如,标准 int 的大小为 4 个字节,而 char 类型的长度为 2 个字节。当算术运算涉及长度不等的整数数据类型时,编译器会采用整数提升策略。
整数提升
一般原则是,小于 int 的 整数 类型在执行运算时会进行提升。如果原始类型的所有值都可以表示为 int,则较小类型的值将转换为 int;否则,将转换为 unsigned int。
必须理解整数提升的概念,才能编写可靠的 C 代码,并避免与数据类型大小以及较小整数类型的算术运算相关的意外问题。
示例
在此示例中,两个变量a 和 b 似乎存储了相同的值,但它们并不相等。
#include <stdio.h> int main(){ char a = 251; unsigned char b = a; printf("a = %c", a); printf(" b = %c", b); if (a == b) printf(" Same"); else printf(" Not Same"); return 0; }
输出
运行此代码时,将产生以下输出 -
a = b = Not Same
之所以会得到这样的输出,是因为在比较过程中,"a"和"b"被视为整数。"a"是一个有符号字符,转换为整数后结果为 -5;而"b"是一个无符号字符,转换为整数后结果为 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"中,首先求解括号。所有变量均为有符号字符类型,该类型长度为 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。
简而言之,我们有以下整数提升规则 -
字节值和短整型 (byte) 值 - 它们会被提升为 int。
如果一个操作数是长整型 (long) - 则整个表达式会被提升为长整型 (long)。
如果一个操作数是浮点型 (float) - 则整个表达式会被提升为浮点型。
如果任意一个操作数为双精度型 - 结果将提升为双精度型。
示例
此处,变量 x 和 y 为 char 数据类型。对它们执行除法运算时,它们将自动提升为 int 类型,并将结果存储在 z 中。
#include <stdio.h> int main(){ char x = 68; char y = 34; printf("The value of x is: %d", x); printf(" The value of y is: %d", y); char z = x/y; printf(" The value of z: %d", z); return 0; }
输出
运行此代码时,将产生以下输出 -
The value of x is: 68 The value of y is: 34 The value of z: 2