这里发生了什么?
#include <stdio.h>
int main (void)
{
int x = 'HELL';
printf("%d\n", x);
return 0;
}
印刷1212501068
我预计会出现编译错误。
欢迎解释=)
这里发生了什么?
#include <stdio.h>
int main (void)
{
int x = 'HELL';
printf("%d\n", x);
return 0;
}
印刷1212501068
我预计会出现编译错误。
欢迎解释=)
1212501068
十六进制是0x48454c4c
.
0x48
是 的 ASCII 码H
。0x45
是 的 ASCII 码E
。0x4c
是 的 ASCII 码L
。0x4c
是 的 ASCII 码L
。请注意,此行为是实现定义的,因此不可移植。一个好的编译器会发出警告:
$ gcc test.c
test.c: In function 'main':
test.c:4:11: warning: multi-character character constant [-Wmultichar]
在 C 中,单引号用于表示字符,在内存中用数字表示。当您将多个字符放在单引号中时,编译器会根据需要将它们组合成一个值,只要它记录了该过程即可。
查看您的号码,1212501068 是 0x48454C4C。如果你把这个数字分解成字节,你得到48
或'H',45
或'E'和两次4C
或'L'
其他人已经解释了发生的事情。至于解释,我引用C99标准草案(N1256):
6.4.4.4 字符常量
[...]
整数字符常量的类型为
int
。包含映射到单字节执行字符的单个字符的整数字符常量的值是被解释为整数的映射字符表示的数值。包含多个字符(例如,'ab')或包含不映射到单字节执行字符的字符或转义序列的整数字符常量的值是实现定义的。如果整数字符常量包含单个字符或转义序列,则其值是将具有单个字符或转义序列的值的 char 类型的对象转换为 int 类型时产生的值。
对相关句子的强调是我的。
1212501068 的十六进制输出为:0x48 0x45 0x4C 0x4C
在ASCII 表中查找它,您会看到这些是HELL
.
顺便说一句:围绕多字符值的单引号不是标准化的。
围绕多个字符的单引号的确切解释是实现定义的。但很常见的是它要么以 Big-Endian 或 Little-Endian 整数的形式出现。(从技术上讲,实现可以以它选择的任何方式解释它,包括随机值)。
换句话说,根据平台的不同,看到它出现时我不会感到惊讶:0x4C 0x4C 0x45 0x48
,或1280066888
线:
int x = 'HELL';
将“HELL”的十六进制值保存到内存中,它是 0x48454c4c == 1212501068。
该值只是 'HELL' 解释为int
(通常为 4 个字节)。
如果你试试这个:
#include <stdio.h>
int main (void)
{
union {
int x;
char c[4];
} u;
int i;
u.x = 'HELL';
printf("%d\n", u.x);
for(i=0; i<4; i++) {
printf("'%c' %x\n", u.c[i], u.c[i]);
}
return 0;
}
你会得到:
1212501068
'L' 4c
'L' 4c
'E' 45
'H' 48