奇怪的C行为

时间:2013-09-07 19:30:31

标签: c

这里发生了什么?

#include <stdio.h>
int main (void)
{
  int x = 'HELL';
  printf("%d\n", x);
  return 0;
}

打印1212501068

我预计会出现编译错误。

欢迎解释=)

6 个答案:

答案 0 :(得分:13)

十六进制中的

12125010680x48454c4c

  • 0x48H的ASCII代码。
  • 0x45E的ASCII代码。
  • 0x4cL的ASCII代码。
  • 0x4cL的ASCII代码。

请注意,此行为是实现定义的,因此不可移植。一个好的编译器会发出警告:

$ gcc test.c
test.c: In function 'main':
test.c:4:11: warning: multi-character character constant [-Wmultichar]

答案 1 :(得分:9)

在C中,单引号用于表示字符,这些字符在数字内存中表示。当您在单引号中放置多个字符时,编译器会将它们组合在一个值中,但只要它记录了该过程。

查看您的号码,1212501068是0x48454C4C。如果将此数字分解为字节,则会获得48或“H”,45或“E”以及两次4C或“L”

答案 2 :(得分:3)

十六进制的1212501068输出为:0x48 0x45 0x4C 0x4C

ASCII table中查找,您会看到这些是HELL的代码。

BTW:围绕多字符值的单引号不是标准化的 实现定义的是围绕多个字符的单引号的准确解释。但它常常以Big-Endian或Little-Endian整数形式出现。 (从技术上讲,实现可以解释它它选择的任何方式,包括随机值。)

换句话说,根据平台的不同,我不会惊讶地发现它是:0x4C 0x4C 0x45 0x481280066888

this question以及this site上,您可以看到此行为的实际用途。

答案 3 :(得分:3)

其他人已经解释了发生了什么。至于解释,我引用C99标准草案(N1256):

  

6.4.4.4字符常量

     

[...]

     

整数字符常量的类型为int。包含映射到单字节执行字符的单个字符的整数字符常量的值是解释为整数的映射字符的表示的数值。 包含多个字符的整数字符常量的值(例如,&#39; ab&#39;),或者包含不映射到单字节执行字符的字符或转义序列,是实现定义的。 如果整数字符常量包含单个字符或转义序列,则其值是当char类型的对象的值为单个字符或转义序列的值时产生的值转换为int。

对相关句子的强调是我的。

答案 4 :(得分:1)

行:

int x = 'HELL';

保存到'HELL'的内存十六进制值,它是0x48454c4c == 1212501068。

答案 5 :(得分:0)

该值只是'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