C 语言 char 类型详解

1. 挂羊头卖狗肉

虽然名字叫 char(character,字符),但在底层 char 完全是一个整数类型。C 语言根本不知道什么是字母 A,它只知道数字 65(ASCII 码)。

因为它是整数,所以可以直接对它进行加减乘除。例如 'a' + 1 得到 'b'(即 97 + 1 = 98)。这种字符与数字不分家的设计在汇编层面很高效,但在高级语言层面非常反直觉。

2. 符号歧义

这是 char 最容易引发跨平台 Bug 的地方。在 C 语言中,如果写 int,它100%代表带符号的整数。

但是,如果写 char,它到底是 signed char 还是 unsigned char,C 标准并没有规定,而是由编译器和硬件平台决定的:

  • 在 x86/AMD64 架构上,通常是 signed char(范围 -128 到 127);

  • 在 ARM 架构上,通常是 unsigned char(范围 0 到 255);

如果你在代码中写了 char c = 200;,在 x86/AMD64 上它会溢出变成负数,而在 ARM 上它是正常的 200。这就导致代码在换个平台编译时突然崩溃。

3. 字符常量的类型其实是 int

在 C 语言中,用单引号括起来的字符字面量(比如 'a'),它的类型不是 char,而是 int

如果运行 printf("%zu", sizeof('a'));,在绝大多数现代系统上输出的结果是 4sizeof(int)),而不是你以为的 1。只有当你显式声明 char c = 'a'; 时,这个 int 类型的 97 才会被截断并赋值给 1 个字节大小的变量 c

4. 虚假的字符串

C 语言没有真正的 string 类型,所谓的字符串只是一串连续的 char 加上一个看不见的 \0 作为结尾标记。这意味着你要像操作内存一样去操作字符串(使用指针、数组)。

忘记加 \0、数组越界、缓冲区溢出……这些 C 语言中声名狼藉的安全漏洞,很大一部分都是因为 char 数组(字符串)这种简陋的设计引起的。

5. 在现代编码下的词不达意

在 C 语言诞生的 70 年代,世界只认 ASCII 码,一个 char(1 个字节)完美对应一个英文字母或符号,名字叫字符非常贴切。

但在如今的 Unicode(UTF-8)时代,一个汉字可能需要 3 个字节,一个 Emoji 表情可能需要 4 个字节。此时,一个 char 根本装不下一个真正的字符。在现代 C 语言编程中,char 实际上代表的是一个字节(Byte)的原始内存数据,而不是阅读意义上的字符。


C 语言 char 类型详解
https://flowerdown.org/posts/20250705-153515
作者
Unrealfeathers
发布于
2025年7月5日
许可协议