2015-07-10 77 views
1

多个字符为什么这个计划让输出'y'分配在焦炭

#include <stdio.h> 

int main(void) { 
    char ch='abcdefghijklmnopqrstuvwxy'; 
    printf("%c",ch); 
    return 0; 
} 

Code at ideone

+1

请记住,单引号字符常量的类型是“int”,但是您将它分配给一个“char”,所以它必须被截断为单个字符。 – unwind

+0

可能的重复:http://stackoverflow.com/questions/13384731/multibyte-integers-variables-in-c/13384799#13384799 –

+0

双C问题:http://stackoverflow.com/questions/29101247/assign-2 -char-to-an-int –

回答

10

这是一个多字符文字。

包含多个c-char的普通字符文字是 多字符文字。多字符文字具有类型int和 实现定义的值

另外,从6.4.4.4/10在C11规格

一个整数的字符常数具有int类型。整数 字符常量的值包含映射到 单字节执行字符的单个字符,这是将映射字符的 表示形式的数值解释为整数。包含多于一个 字符(例如,“AB”),或含有一个字符或转义序列 不映射到单字节执行字符,整数字符常数的 值是 实施 - 定义为。如果整数字符常量包含单个字符或转义序列的 ,则其值为 时,如果char类型的值为单个 字符或转义序列的对象转换为int类型,则该值为 。

所以系统(假设4字节INT)就行char ch = 'abcdefghijklmnopqrstuvwxy'可能编译为:

char ch = 0x76777879; // SOME int value (may be different, but documented in the compiler documents) 

ch将ASCII编码被分配'abcdef...y'which may be equivalent to(int)0x616263646566...79和溢出的整数。这就是为什么gcc生成下列警告的原因:

multicharlit.c:在函数“主”:
multicharlit.c:4:启用 字符常量太长其类型是:13:警告默认]
multicharlit.c:4:5:警告:溢出在隐恒定转化率 [-Woverflow]

似乎在系统上,至少显著使用8个比特分配给ch。因为你的字符文字是不变的,这最有可能发生在编译时:

$ cat multicharlit.c 
#include <stdio.h> 

int main(void) { 
    char ch='abcdefghijklmnopqrstuvwxy'; 
    printf("%c",ch); 
    return 0; 
} 

$ gcc -O2 -fdump-tree-optimized multicharlit.c 
$ cat multicharlit.c.143t.optimized 

;; Function main (main) (executed once) 

main() 
{ 
<bb 2>: 
    __builtin_putchar (121); 
    return 0; 

} 

还偷了一些善良的unwind's comment

请记住,(例如,当我与gcc编译如下情况发生)单引号字符常量的类型是int, 但您将它分配给char,所以它必须被截断为 单个字符。的'a'例如

类型是在Cint。 (不要与'a'C++这是一个char混淆。论'ab'另一方面类型intCC++

现在,当你这个int类型分配给一个char类型和值如果多于这个值,可以用char来表示,那么需要进行一些压缩以将结果适用于更宽的类型char,并且实际结果是实现定义的。

+1

@LoveToCode:编译器必须记录实现定义的行为,并且据推测,您正在使用的编译器将多字符常量中的最后一个字符放入字符值中。它可能是实现选择的第一个,第四个或任何其他字符 - 它只需记录它选择做什么(然后它也应该这样做)。 –

0

如果打算打印出abcdefghijklmnopqrstuvwxy,那么你应该存储它到字符串变量而不是一个字符的一个(炭CH [50] =炭abcdefghijklmnopqrstuvwxy)。

字符串变量可以容纳多个字符,其中char变量用于保存一个字符。