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 - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 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 - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 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 代码,并避免与数据类型大小以及较小整数类型的算术运算相关的意外问题。

示例

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

#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) - 则整个表达式会被提升为浮点型。

  • 如果任意一个操作数为双精度型 - 结果将提升为双精度型。

示例

此处,变量 xy 为 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