为何十六进制转义序列'\x90'与十六进制数0x90存在差异?
为什么
'\x90'作为char是负值,而0x90作为int是正值? 嘿,这个问题的核心其实藏在有符号整数的补码规则和不同数据类型的位宽特性里,我一步步给你讲明白:
1. char类型的默认有符号性
绝大多数C/C++编译器中,char默认是有符号类型(signed char),占1字节(8个二进制位)。
当你写'\x90'时,这个十六进制转义序列对应的二进制是 10010000。对于有符号数来说,二进制的最高位是符号位:
- 最高位为
0代表正数 - 最高位为
1代表负数
这个二进制数的最高位是1,所以会被解读为负数。按照补码的计算规则:
- 先对除符号位外的部分取反:
01101111 - 再加1得到原码:
01110000(十进制是112) - 所以最终这个char的值是
-112,而不是你以为的144。
2. int类型的无符号扩展特性
int类型占4字节(32位),0x90作为十六进制数,对应的二进制是:00000000 00000000 00000000 10010000
这里的最高位是0,所以直接被解读为正数,十进制就是144——这和你看到的结果一致。
3. 关键补充:符号扩展与无符号char
- 如果你显式声明
unsigned char uc = '\x90';,那它的值就是144了。因为无符号类型没有符号位,最高位只是普通的数值位,直接按8位二进制计算就是144。 - 当你把signed char的
'\x90'强制转换成int时,会发生符号扩展:编译器会把char最高位的1填充到int的所有高位,变成11111111 11111111 11111111 10010000,这个int值依然是-112,这就是两种类型取值差异的本质。
举个代码例子验证
#include <stdio.h> int main() { char c = '\x90'; unsigned char uc = '\x90'; int i = 0x90; printf("默认char c的值:%d\n", c); // 输出-112(取决于编译器默认char为signed) printf("unsigned char uc的值:%u\n", uc); // 输出144 printf("int i的值:%d\n", i); // 输出144 printf("char转int后的值:%d\n", (int)c); // 输出-112(符号扩展) return 0; }
简单来说:不是十六进制本身有区别,而是char(默认有符号)和int的位宽、符号规则不同,导致同一个十六进制序列被解读成了不同的十进制值。
内容的提问来源于stack exchange,提问作者holahola




