Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 奇怪的行为_C - Fatal编程技术网

C 奇怪的行为

C 奇怪的行为,c,C,这里发生了什么 #include <stdio.h> int main (void) { int x = 'HELL'; printf("%d\n", x); return 0; } #包括 内部主(空) { int x='地狱'; printf(“%d\n”,x); 返回0; } 打印1212501068 我预期会出现编译错误 欢迎解释=)1212501068十六进制是0x48454c 0x48是H的ASCII码 0x45是E的ASCII码 0x4c是L的ASCI

这里发生了什么

#include <stdio.h>
int main (void)
{
  int x = 'HELL';
  printf("%d\n", x);
  return 0;
}
#包括
内部主(空)
{
int x='地狱';
printf(“%d\n”,x);
返回0;
}
打印
1212501068

我预期会出现编译错误


欢迎解释=)

1212501068
十六进制是
0x48454c

  • 0x48
    H
    的ASCII码
  • 0x45
    E
    的ASCII码
  • 0x4c
    L
    的ASCII码
  • 0x4c
    L
    的ASCII码
请注意,此行为是实现定义的,因此不可移植。好的编译器会发出警告:

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

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


看看你的号码,1212501068是0x48454C。如果将该数字分解为字节,则会得到
48
或'H'、
45
或'E'以及两次
4C
或'L'

以十六进制形式输出的1212501068:
0x48 0x45 0x4C 0x4C

在中查找,您将看到这些是
HELL
的代码

顺便说一句:多字符值周围的单引号未标准化。
多个字符周围单引号的精确解释由实现定义。但很常见的是,它要么是一个大端整数,要么是一个小端整数。(从技术上讲,实现可以选择任何方式对其进行解释,包括随机值)

换句话说,根据平台的不同,我会毫不惊讶地看到它的结果是:
0x4C 0x4C 0x45 0x48
,或者
1280066888

在上面,也在上面,你可以看到这种行为的实际用途。

行:

int x = 'HELL';

将“HELL”的十六进制值保存到内存中,它是0x48454C==1212501068。

该值只是解释为
int
(通常为4个字节)的“HELL”

如果您尝试以下方法:

#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;
}

其他人解释了发生的事情。关于解释,我引用C99标准草案(N1256):

6.4.4.4字符常数 [……]

整型字符常量的类型为
int
。包含映射到单字节执行字符的单个字符的整数字符常量的值是被解释为整数的映射字符表示形式的数值包含多个字符(如“ab”)的整型字符常量的值,或包含不映射到单字节执行字符的字符或转义序列的整型字符常量的值由实现定义。如果整型字符常量包含单个字符或转义序列,它的值是当值为单个字符或转义序列的char类型的对象转换为int类型时产生的值



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

的确如此。但这是定义的行为吗?它是实现定义的。:-)我也没有见过用单引号来捕捉多个字母单词……我很难同意这是一个实际的用途……@OliCharlesworth:我已经见过它在快速协议解析器中使用过好几次了。例如:霍尼韦尔条形码扫描仪使用3个字母的命令进行通信。这些命令是人类可读的,并且仍然可以非常快地转换为int。不总是很漂亮,但绝对有效。不,它不是UB。它是实现定义的。看看我的答案。那么,给我们看一些奇怪的东西。我们正在等待。哈哈,你很有趣@HotLicksPol0nium,我认为@HotLicks的观点是“要求代码的问题必须证明对正在解决的问题的最低理解。包括尝试的解决方案,为什么它们不起作用,以及预期的结果。”除非你说为什么
1212501068
是一个意外的结果,不清楚应该解释什么。当然,你不是在问代码,但是关于预期结果的问题仍然是一个很好的经验法则。我已经看到这个问题被问过了,但是我找不到重复的。不管怎么说,我不明白为什么对这些毫无意义的问题的答案会被投这么多票。@sashoalm的答案不会因为其他地方没有回答而被投票,他们会因为正确而被投票。如果这个问题被问得太多,应该很容易就把它作为一个dup关闭(尽管如果你担心east回答了不应有的选票,我不认为一个关闭的问题会妨碍选票的获得)。这是一个模糊的语言特征,许多关于它的书籍可能会完全忽略这个特征。即使是那些碰巧涉及到这个问题的书,除了从头读到尾,你会建议如何在书的索引中定位该功能?@mah在“字符常量”下查找,因为这是C标准中所称的。@Jens我在索引中查找了我大学时代的两篇C/C++文本,其中没有一篇列出“字符常量”。我还查看了MichaelChovanec发布的Amazon链接,并使用Amazon的“查看内部”功能访问了它的索引……这里也没有。我第一次评论的要点是,作为语言标准的一部分绝不意味着全部(或大部分)好的语言书籍会记录它——尤其是模糊的特征。你的评论(即测试时的结果)似乎加强了这一点。为什么C++的书推荐一个关于C的问题?……最好把它们组合成一个值。这是乐观的。由于行为依赖于实现,编译器可以选择将每个“multichar”常量映射到值
-2
(因此不是很有用)。唯一的限制是它必须记录其行为。该值由实现定义-凯斯·汤普森:如果你要去唐沃的话
1212501068
'L' 4c
'L' 4c
'E' 45
'H' 48