2015-07-10 90 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變量用於保存一個字符。