整数提升
首先要理解一个关键概念:整数提升。

(图片来源网络,侵删)
在 C 语言中,当一个比 int 类型小的整数类型(如 char, short)在表达式中使用时,它会被自动提升为 int 类型(int 能表示原始类型的所有值)或者 unsigned int 类型。
这意味着,当你尝试将一个 char 赋值给一个 int 时,编译器会自动进行这个转换,这个转换的规则至关重要:
-
char是 无符号的 (unsigned char):- 它的值会被零扩展到
int的大小,也就是说,高位(新增加的位)全部用0填充。 unsigned char c = 250;(二进制11111010),转换成int后,仍然是...00000000 11111010,其十进制值仍然是250。
- 它的值会被零扩展到
-
char是 有符号的 (signed char,这是char的默认类型):
(图片来源网络,侵删)- 它的值会被符号扩展到
int的大小,也就是说,高位会用原始值的符号位(最高位)来填充。 - 这是最容易出问题的地方!
- 示例 1(正数):
signed char c = 'A';(ASCII 码是 65)。char的二进制是01000001,符号位是0,所以高位用0填充,转换成int后是...00000000 01000001,其十进制值是65,这符合预期。 - 示例 2(负数):
signed char c = -10;,在 8 位char中,-10的二进制是11110110(补码表示),符号位是1,所以高位用1填充,转换成int后是...11111111 11110110,这个int值是一个非常大的负数(-10)。
- 它的值会被符号扩展到
直接赋值(最常见)
这是最简单、最直接的方法,利用 C 语言的自动类型转换(整数提升)。
#include <stdio.h>
int main() {
// 1. ASCII 字符 'A' -> 整数 65
char c1 = 'A';
int i1 = c1; // 自动类型转换
printf("'%c' (char) -> %d (int)\n", c1, i1); // 输出: 'A' (char) -> 65 (int)
// 2. 数字字符 '5' -> 整数 53 (ASCII 码)
char c2 = '5';
int i2 = c2;
printf("'%c' (char) -> %d (int)\n", c2, i2); // 输出: '5' (char) -> 53 (int)
// 3. 有符号 char 的负数
signed char c3 = -10;
int i3 = c3; // 发生符号扩展
printf("%d (signed char) -> %d (int)\n", c3, i3); // 输出: -10 (signed char) -> -10 (int)
// 4. 无符号 char 的值
unsigned char c4 = 250;
int i4 = c4; // 发生零扩展
printf("%u (unsigned char) -> %d (int)\n", c4, i4); // 输出: 250 (unsigned char) -> 250 (int)
return 0;
}
对于绝大多数情况,直接赋值 int i = my_char; 就足够了。
使用强制类型转换
当你想让代码的意图更明确,或者处理一些复杂的表达式时,可以使用强制类型转换。
语法:(目标类型) 变量

(图片来源网络,侵删)
#include <stdio.h>
int main() {
char c = 'B';
int i = (int)c; // 显式地进行类型转换
printf("'%c' -> %d\n", c, i); // 输出: 'B' -> 66
// 强制转换在表达式中的使用
double d = 10.5;
// 下面的代码会有警告,因为 int 和 double 运算,double 会提升
// int result = d + c;
// 使用强制转换可以避免警告或明确意图
int result = (int)d + (int)c; // 先将 d 和 c 都转为 int,再相加
printf("(int)%.1f + (int)'%c' = %d\n", d, c, result); // 输出: (int)10.5 + (int)'B' = 76
return 0;
}
强制转换不会改变转换的规则(仍然是整数提升),但它让代码的意图更清晰,并可以帮助解决一些编译器警告。
将字符数字转为数值(常见需求)
你的 char 变量里存的是 '0', '1', '2'...'9',你希望得到对应的整数 0, 1, 2...9。
错误做法:int num = '0'; 得到的是 48,而不是 0。
正确做法:利用 ASCII 码的连续性,减去字符 '0' 的 ASCII 码值。
#include <stdio.h>
int main() {
char c_digit = '7';
int i_value;
// 正确做法:减去 '0' 的 ASCII 码
i_value = c_digit - '0';
// '7' 的 ASCII 码是 55, '0' 的 ASCII 码是 48
// 55 - 48 = 7
printf("'%c' -> %d\n", c_digit, i_value); // 输出: '7' -> 7
// 这是一个非常经典和常用的 C 语言技巧
return 0;
}
使用标准库函数 atoi
如果你有一个字符串(char*),并且想把它转换成一个整数,可以使用 atoi 函数(ASCII to Integer)。
注意:atoi 的输入是 const char*,而不是单个 char。
#include <stdio.h>
#include <stdlib.h> // 必须包含这个头文件才能使用 atoi
int main() {
const char* str = "12345"; // 这是一个字符串
int num = atoi(str);
printf("字符串 \"%s\" 转换为整数: %d\n", str, num); // 输出: 字符串 "12345" 转换为整数: 12345
const char* str_with_alpha = "42abc";
num = atoi(str_with_alpha); // atoi 会停止在第一个非数字字符
printf("字符串 \"%s\" 转换为整数: %d\n", str_with_alpha, num); // 输出: 字符串 "42abc" 转换为整数: 42
return 0;
}
总结与最佳实践
| 场景 | 推荐方法 | 示例 | 注意事项 |
|---|---|---|---|
将单个 char 转为其 ASCII 码值 |
直接赋值 | int i = 'A'; |
char 是 signed 且为负数,会进行符号扩展。 |
将单个 char 转为其 ASCII 码值 |
强制转换 | int i = (int)'A'; |
与直接赋值效果相同,但意图更明确。 |
将字符 '0'-'9' 转为数字 0-9 |
减去 '0' | int i = '7' - '0'; |
最常用、最标准的方法,高效且易读。 |
| 将字符串(如 "123")转为整数 | atoi 函数 |
int i = atoi("123"); |
需要包含 <stdlib.h>,输入是 const char*。 |
核心要点回顾:
- 默认转换规则:
char默认是signed char,转换时会进行符号扩展,如果不想这样,请使用unsigned char。 - 字符数字转数值:一定要用
char - '0'的方法,而不是直接赋值。 - 明确意图:使用强制类型转换
(int)可以让代码更清晰,避免潜在警告。 - 字符串转换:需要转换整个字符串时,使用
atoi或更安全的strtol函数。
