一、 核心前提:char
是特殊的int
在C语言中,char
类型本质上是一个小型整数,它存储的是字符对应的ASCII码。然而,一个单独的字符字面量(如'B'
)在表达式中会被 提升(promoted) 为int
类型。
举例:
一个char
变量像一个小盒子,只能装1个字节的东西。但'B'
这个字面量本身,在被使用时,计算机会暂时把它放进一个标准大小的int
盒子(通常4字节)里处理。
#include <stdio.h>
int main() {
char grade_char = 'B'; // 'B' (值66) 被存入1字节的变量中
// sizeof('B') 会显示 int 的大小
printf("字面量 'B' 在表达式中的大小: %zu 字节\n", sizeof('B'));
// sizeof(grade_char) 会显示 char 的大小
printf("char 变量 grade_char 的大小: %zu 字节\n", sizeof(grade_char));
}
// 输出:
// 字面量 'B' 在表达式中的大小: 4
// char 变量 grade_char 的大小: 1
二、 多字节字符常量:一个int
里的“俄罗斯套娃”
C语言允许一个“魔术操作”:将多个字符塞进一对单引号里,形成一个多字节字符常量,它的类型是int
。
举例:'FATE'
这相当于把4个独立的8位char
(F, A, T, E)打包进了一个32位的int
中。
- 值的构成:它的整数值是由每个字符的ASCII码通过位运算组合而成,具体值是实现定义的(取决于编译器)。在GCC/Clang等常见编译器上,其值的十六进制表示为
0x46415445
,十进制为1,178,686,533
。'F'
->0x46
'A'
->0x41
'T'
->0x54
'E'
->0x45
#include <stdio.h>
int main() {
int fate_value = 'FATE';
// 使用 %X 格式化输出十六进制,可以清晰看到拼接结构
printf("'FATE' 的十六进制值: 0x%X\n", fate_value);
printf("'FATE' 的十进制值: %d\n", fate_value);
}
// 输出:
// 'FATE' 的十六进制值: 0x46415445
// 'FATE' 的十进制值: 1178686533
三、 截断:当int
遇到char
当一个大的数据类型(如32位的int
)被赋值给一个小的类型(如8位的char
)时,会发生截断。
举例:
这就像把一个大水桶(int
)里的水倒进一个小水杯(char
)里,只有最底下的那部分水能装进去。对于数字,保留的是最低有效字节 (Least Significant Byte, LSB)。
#include <stdio.h>
int main() {
// 'FATE' 的值是 0x46415445
// 最低有效字节是 0x45, 也就是 'E' 的 ASCII 码
char grade = 'FATE';
printf("当 'FATE' 赋值给 char 时,结果是: %c\n", grade);
printf("对应的 ASCII 码是: %d\n", grade);
}
// 输出:
// 当 'FATE' 赋值给 char 时,结果是: E
// 对应的 ASCII 码是: 69
四、 物理存储与字节序 (Endianness)
字节序规定了一个多字节数据在内存中的物理排列顺序。
- 二进制是根本:计算机只懂二进制。十六进制是方便人类读写二进制的“简写”。
- 小端序 (Little-Endian):最低有效字节存储在最低的内存地址。(主流PC为此模式)
- 大端序 (Big-Endian):最高有效字节存储在最高的内存地址。
举例:int fate_int = 'FATE';
在小端序机器上的内存布局
fate_int
的值为0x46415445
,它在内存中的4个字节内容会是:
内存地址 | N |
N+1 |
N+2 |
N+3 |
---|---|---|---|---|
存放内容 | 0x45 ('E') |
0x54 ('T') |
0x41 ('A') |
0x46 ('F') |
五、 长度限制与合法性
多字节字符常量并非无限长,它受到int
类型大小的物理限制。
-
情况1:正好 (≤ 4 字符)
int val = 'FATE';
-> 合法,值由4个字符构成。 -
情况2:略长 (> 4 字符)
int val = 'ABCDE';
-> 通常会收到编译器警告,并发生截断,只取最后的4个字符'BCDE'
来计算值。 -
情况3:过长 (>> 4 字符)
int val = 'FSFIJHISJFHIOHIJJIO';
-> 这是一个不合法的字面量,因为它在物理上无法被存入一个int
。编译器会直接报错。
Comments NOTHING