请解释这个结果。 printf("%c",' abcd')

时间:2014-10-31 08:13:05

标签: c memory character-encoding printf

#include <stdio.h>

int main()
{
    printf("%c\n", 'abcd');
    printf("%p\n", 'abcd');
    printf("%c\n", 0x61626364);
    printf("%c\n", 0x61626363);
    printf("%c\n", 0x61626365);
    return 0;
}

我想问这一行:printf(&#34;%c \ n&#34;,&#39; abcd&#39;);
在这一行中,结果是&#39; d&#39;但是,我无法理解为什么&#39; d&#39;出来了。
我试着寻找其他的回忆。在这种情况下,我发现其他记忆都包含所有字母 请解释一下为什么结果是&#39; d&#39;以及为什么其他记忆都包含所有字母 谢谢。

4 个答案:

答案 0 :(得分:4)

'abcd'是一个多字符常量,其值是实现定义的。

  

C11§6.4.4.4字符常量第10节

     

整数字符常量的类型为int。整数字符常量的值   包含映射到单字节执行字符的单个字符是   解释为整数的映射字符表示的数值。   包含多个字符的整数字符常量的值(例如,   'ab',或包含未映射到单字节的字符或转义序列   执行字符,是实现定义的。如果包含整数字符常量   单个字符或转义序列,其值是当对象具有时产生的值   类型char,其值是单个字符或转义序列的值转换为   输入int

一个常见的实现为'abcd'提供'a' * 256 * 256 * 256 + 'b' * 256 * 256 + 'c' * 256 + 'd'1633837924)的值,您可以使用"%d"打印它在实现中的值。虽然是合法的C,但它在实践中很少使用。

答案 1 :(得分:1)

您的代码错误。使用最新的GCC编译器编译时,使用

启用警告
gcc -Wall -Wextra u.c

你得到了

 u.c: In function 'main':
 u.c:5:20: warning: multi-character character constant [-Wmultichar]
      printf("%c\n", 'abcd');
                     ^
 u.c:6:20: warning: multi-character character constant [-Wmultichar]
      printf("%p\n", 'abcd');
                     ^
 u.c:6:5: warning: format '%p' expects argument of type 'void *', but argument 2 has type 'int' [-Wformat=]
      printf("%p\n", 'abcd');
      ^

从技术上讲,您处于糟糕的undefined behavior案例(以及 unspecified behavior 的多字符常量)和{{3}符合标准的实现可能会发生。

我从未见过像'abcd'这样的多字符常量的任何有用情况。我相信它们毫无用处,而且大部分都是历史人工制品。

要解释实际发生的事情,它是特定于实现的(取决于编译器,处理器,优化标志,ABI,运行时环境......),你需要深入了解血腥细节(首先看看生成的汇编程序代码gcc -fverbose-asm -S)以及anything特定printf实现。

根据经验,你应该改进你的代码,以摆脱编译器能够给你的每一个警告(你的编译器有助于警告你)。它们是一些微妙的例外(但是你应该对它们的代码进行评论)。

答案 2 :(得分:1)

printf("%c\n", 'abcd');

如前所述,'abcd'的值是实现定义的。在您的实施中,其值为0x61626364,因此其行为与您的第三次printf调用相同。见下文。

printf("%p\n", 'abcd');

如前所述,%p用于打印指针。 <{1}}不是指针,因此此调用无效。

'abcd'

printf("%c\n", 0x61626364); printf("%c\n", 0x61626363); printf("%c\n", 0x61626365); 的规范如下:

  

如果不存在%c长度修饰符,则l参数将转换为int,并写入生成的字符。

unsigned charint的转化定义明确,并将值{im} unsigned char减少。在大多数实现中,这意味着它需要该数字的最低8位。

UCHAR_MAX+10x616263640x61626363的最低8位为0x616263650x640x63,其中ASCII对应{ {1}},0x65'd',因此ASCII实现将打印这些字符。

答案 3 :(得分:0)

您的代码

printf("%c\n", 'abcd');

导致输出

d

由于&#34;%c&#34;指定单个字符。因为提供了多个字符而不是单个字符,所以多字符常量被转换为&#39;取一个字符,取字符串的最后一个字符。

提供预期单个字符的字符串的结果是&#34;实现定义的&#34;行为。这意味着不同的编译器可以不同地处理它。见stackoverflow.com/multiple-characters-in-a-character-constant