截断
int 和 char 在 C 语言中都是整数类型,但它们的存储大小不同:

int: 通常占用 4 个字节 (32位)。char: 占用 1 个字节 (8位)。
当将一个 int 赋值给一个 char 时,C 编译器会执行一个叫做“截断” (Truncation) 的操作,它会简单地丢弃 int 值中高位(最左边)的 3 个字节,只保留最低位的 1 个字节。
这相当于对 int 值进行模 256 运算(因为 1 字节 = 8 位 = 2^8 = 256 种可能)。
char 的本质:
char 类型在 C 中本质上是一个小整型,它既可以被解释为一个字符(通过 ASCII 码),也可以被解释为一个 -128 到 127 之间的有符号整数,或者 0 到 255 之间的无符号整数,这取决于你如何使用它。
转换方法
主要有两种方法,但它们在底层实现上是等价的。

直接赋值(最常用)
这是最直接、最简单的方法,C 语言会自动进行类型转换,这个过程称为隐式类型转换。
int my_int = 65; char my_char; // 将 int 赋值给 char my_char = my_int; // 自动发生截断
工作原理:
my_int (值为 65) 的二进制表示是 0000 0000 0000 0000 0000 0000 0100 0001。
赋值时,只保留最低的 8 位,即 0100 0001。
my_char 的值就变成了 0100 0001。
解释:
my_char被当作字符输出(使用%c),它会显示为字母 'A',因为 ASCII 码 65 对应 'A'。my_char被当作整数输出(使用%d),它会显示为 65。
使用强制类型转换(显式转换)
为了提高代码的可读性,或者在某些情况下抑制编译器的警告,你可以使用强制类型转换,也叫显式类型转换。
语法:(目标类型) 表达式
int my_int = 65; char my_char; // 使用强制类型转换将 int 转为 char my_char = (char)my_int;
与直接赋值的区别:
- 功能上完全相同:编译器都会执行相同的截断操作。
- 可读性:强制类型转换明确地向其他程序员(和编译器)表示你“知道”故意”要进行这次类型转换。
- 警告:在某些情况下,直接将一个较大的
int赋给char,编译器可能会给出警告,使用强制类型转换可以告诉编译器“别担心,我知道我在做什么”。
重要注意事项和示例
理解截断行为对于正确使用转换至关重要。
示例 1:正数在 0-255 范围内
这种情况最简单,直接保留原值。
#include <stdio.h>
int main() {
int num = 200; // 在 0-255 范围内
char c = (char)num;
printf("int: %d, char (as %%d): %d\n", num, c); // 输出: int: 200, char (as %d): 200
printf("int: %d, char (as %%c): %c\n", num, c); // 输出: int: 200, char (as %c): Û (字符'Û'的ASCII码是200)
return 0;
}
示例 2:正数超出 255 范围(只保留低8位)
这是截断最明显的体现。
#include <stdio.h>
int main() {
int num = 300; // 二进制: ...0001 0010 1100
char c = (char)num; // 只保留 0010 1100, 即十进制的 44
printf("int: %d, char (as %%d): %d\n", num, c); // 输出: int: 300, char (as %d): 44
printf("int: %d, char (as %%c): %c\n", num, c); // 输出: int: 300, char (as %c): , (字符','的ASCII码是44)
return 0;
}
示例 3:负数(有符号 char 的行为)
char 默认是 signed char(范围 -128 到 127),当截断一个负数 int 时,保留的 8 位会被解释为一个负数。
#include <stdio.h>
int main() {
int num = -30; // 32位二进制: 1111 1111 1111 1111 1111 1111 1110 0010
char c = (char)num; // 只保留 1110 0010
// 1110 0010 作为有符号8位整数,其值为 -126
printf("int: %d, char (as %%d): %d\n", num, c); // 输出: int: -30, char (as %d): -126
printf("int: %d, char (as %%c): %c\n", num, c); // 输出: int: -30, char (as %c): û (这是一个控制字符或扩展ASCII字符)
return 0;
}
示例 4:如何正确处理大整数?
如果你只是想获取一个 int 的最低字节,而不关心它是否为负数,可以将 char 声明为 unsigned char,它的范围是 0 到 255,不会进行符号扩展。
#include <stdio.h>
int main() {
int num = -30; // 32位二进制: 1111 1111 1111 1111 1111 1111 1110 0010
unsigned char uc = (unsigned char)num; // 保留 1110 0010,并解释为无符号数
// 1110 0010 作为无符号8位整数,其值为 230 (128 + 64 + 16 + 2 = 230)
printf("int: %d, unsigned char (as %%u): %u\n", num, uc); // 输出: int: -30, unsigned char (as %u): 230
return 0;
}
| 方法 | 语法 | 优点 | 缺点 |
|---|---|---|---|
| 直接赋值 | char c = my_int; |
简洁、方便 | 可读性稍差,可能引起编译器警告 |
| 强制类型转换 | char c = (char)my_int; |
意图明确,可读性好,可抑制警告 | 代码稍长 |
关键要点:
- 核心是截断:
int转char就是丢弃高 24 位,只保留低 8 位。 char是小整数:转换后的char本质上是一个 8 位的值,可以用%c或%d/%u来解释。- 注意符号:
char是signed(默认),截断后的负数会被正确解释为负值,如果需要 0-255 的范围,请使用unsigned char。 - 使用强制转换:为了代码清晰和避免警告,推荐使用
(char)进行显式转换。
