- C 编程教程
- C - 首页
- C 语言基础
- C - 概述
- C - 特性
- C - 历史
- C - 环境搭建
- C - 程序结构
- C - Hello World
- C - 编译过程
- C - 注释
- C - 词法单元
- C - 关键字
- C - 标识符
- C - 用户输入
- C - 基本语法
- C - 数据类型
- C - 变量
- C - 整数提升
- C - 类型转换
- C - 类型强制转换
- C - 布尔类型
- C 语言中的常量和字面量
- C - 常量
- C - 字面量
- C - 转义序列
- C - 格式说明符
- C 语言中的运算符
- C - 运算符
- C - 算术运算符
- C - 关系运算符
- C - 逻辑运算符
- C - 位运算符
- C - 赋值运算符
- C - 一元运算符
- C - 自增和自减运算符
- C - 三元运算符
- C - sizeof 运算符
- C - 运算符优先级
- C - 其他运算符
- C 语言中的决策语句
- C - 决策语句
- C - if 语句
- C - if...else 语句
- C - 嵌套 if 语句
- C - switch 语句
- C - 嵌套 switch 语句
- C 语言中的循环语句
- C - 循环语句
- C - while 循环
- C - for 循环
- C - do...while 循环
- C - 嵌套循环
- C - 无限循环
- C - break 语句
- C - continue 语句
- C - goto 语句
- C 语言中的函数
- C - 函数
- C - 主函数
- C - 按值调用函数
- C - 按引用调用函数
- C - 嵌套函数
- C - 可变参数函数
- C - 用户自定义函数
- C - 回调函数
- C - 返回语句
- C - 递归
- C 语言中的作用域规则
- C - 作用域规则
- C - 静态变量
- C - 全局变量
- C 语言中的数组
- C - 数组
- C - 数组的特性
- C - 多维数组
- C - 将数组传递给函数
- C - 从函数返回数组
- C - 变长数组
- C 语言中的指针
- C - 指针
- C - 指针和数组
- C - 指针的应用
- C - 指针运算
- C - 指针数组
- C - 指针到指针
- C - 将指针传递给函数
- C - 从函数返回指针
- C - 函数指针
- C - 指向数组的指针
- C - 指向结构体的指针
- C - 指针链
- C - 指针与数组
- C - 字符指针和函数
- C - 空指针
- C - void 指针
- C - 野指针
- C - 解引用指针
- C - 近、远和巨型指针
- C - 指针数组的初始化
- C - 指针与多维数组
- C 语言中的字符串
- C - 字符串
- C - 字符串数组
- C - 特殊字符
- C 语言中的结构体和联合体
- C - 结构体
- C - 结构体和函数
- C - 结构体数组
- C - 自引用结构体
- C - 查找表
- C - 点 (.) 运算符
- C - 枚举 (或 enum)
- C - 结构体填充和打包
- C - 嵌套结构体
- C - 匿名结构体和联合体
- C - 联合体
- C - 位域
- C - Typedef
- C 语言中的文件处理
- C - 输入和输出
- C - 文件 I/O(文件处理)
- C 预处理器
- C - 预处理器
- C - 编译指示
- C - 预处理器运算符
- C - 宏
- C - 头文件
- C 语言中的内存管理
- C - 内存管理
- C - 内存地址
- C - 存储类
- 其他主题
- C - 错误处理
- C - 可变参数
- C - 命令执行
- C - 数学函数
- C - static 关键字
- C - 随机数生成
- C - 命令行参数
- C 编程资源
- C - 问答
- C - 快速指南
- C - 速查表
- C - 有用资源
- C - 讨论
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("\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。
示例
这里,变量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("\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