2013-09-26 56 views
2

知道下面的代碼被打破內返回值關於存儲的getchar()的燒焦變

#include <stdio.h> 
int 
main(int argc, char* argv[]) 
{ 
    char single_byte = getchar(); 

    while (single_byte != EOF) { 
    single_byte = getchar(); 
    printf("getchar() != EOF is %d.\n", single_byte != EOF); 
    if (single_byte == EOF) 
     printf("EOF is implemented in terms of 0x%x.\n", single_byte); 
    } 

    return 0; 
} 

雖然我預料的典型輸出它(使用/dev/urandom作爲輸入流爲例)將是最後EOF is implemented in terms of 0xff,而不是以下

$ ./silly < /dev/urandom 
getchar() != EOF is 1. 
getchar() != EOF is 1. 
// ... 
getchar() != EOF is 0 
EOF is implemented in terms of 0xffffffff. 

此外,0xffffffff不能存儲到一個單一的字節...

預先感謝您

回答

1

知道下面的代碼被打破 - getchar()返回int不是char -

好!

char single_byte = getchar(); 

這是有問題的是不止一種方式。

我會假設CHAR_BIT == 8EOF == -1。 (我們知道EOF爲負,int類型; -1是一個典型的價值 - 事實上,我從來沒有聽說過有任何其他的價值吧。)

平原char可以或者帶符號。

如果它是無符號的,的single_byte值將是剛讀出的字符的任一個值(表示爲unsigned char和輕易地轉化爲純char),或轉化到EOFchar的結果。通常,EOF爲-1,轉換結果將爲CHAR_MAX或255。您將無法區分EOF和實際輸入值255 - 並且由於/dev/urandom返回等概率的所有字節值(以及從不幹涸),你遲早會看到一個0xff字節。

但是,這不會終止您的輸入循環。你的比較(single_byte == EOF)永遠不會是真的;由於single_byte在這種情況下屬於無符號類型,因此它永遠不會等於EOF。即使從有限文件中讀取數據,而不是像/dev/urandom這樣的無限制設備讀取,也會產生無限循環。 (你可能寫了(single_byte == (char)EOF),但當然這並不能解決潛在的問題。)

由於你的循環確實終止了,所以我們可以得出這樣的結論:在你的系統上對普通的char進行簽名。

如果明碼char已簽名,則情況會稍微複雜一些。如果您讀取範圍爲0..127的字符,則其值將存儲在single_byte中。如果讀取範圍爲128..255的字符,則int值爲轉換爲char;由於char已簽名且值超出範圍,因此轉換結果爲實現定義的。對於大多數實現,該轉換將映射128到-128,129到-127,... 255到-1。如果getchar()返回EOF,其(通常)爲-1,則轉換被良好定義並且產生-1。再次,您不能區分EOF和值爲-1的輸入字符。 (實際上,從C99開始,轉換也可以引發實現定義的信號。幸運的是,據我所知,還沒有實現真正做到這一點。)

if (single_byte == EOF) 
    printf("EOF is implemented in terms of 0x%x.\n", single_byte); 

同樣,這種情況將是真實的或者如果getchar()實際返回EOF或者如果你只是讀一個字符與價值0xff%x格式需要unsigned int類型的參數。 single_byte類型爲char,這幾乎肯定會被提升爲int。現在,您可以使用unsigned int格式打印int如果該值在兩種類型的可表示範圍內。但由於single_byte的值是-1(它只是比較等於EOF),它不在該範圍內。 printf,與"%x"格式,假定該參數是類型unsigned int(這不是轉換)。並且0xffffffff是可能的結果,取32位int-1,並假設它確實是unsigned int

我只是注意到,將getchar()的結果存儲在一個int對象中比分析將它存儲在char中時發生的情況要容易得多。

0

檔案結尾是int類型的宏定義一個擴展到某個負積分常量表達式(通常,-1)。

+0

當然,但畢竟我只是打印'char'的'single_byte'的值。我問:如何'single_byte'(它確實是** 1 **字節)可以是'0xffffffff'? – giuscri

+0

你試過打印EOF嗎? http://ideone.com/wHcIq8 - 您需要了解的是EOF在您的系統中評估的內容。你會得到你的答案。 – Sadique

+0

因爲我打印'single_byte',導致我的困惑?意思是'%x'打印'-1'不管它來自哪裏,但是在'1'上使用2的補碼被認爲是一個32位的字?對嗎?首先評估'single_byte',然後打印出指令詢問的方式。 – giuscri

0

EOF是不是一個真正的性格讓以允許getchar()返回一個有效的字符或EOF的結果,它採用了黑客攻擊,而返回類型爲int。您必須將其投射到char之後您確定它不是EOF

這是設計不佳的API的教科書示例。

0

它似乎是(char) -1(int) -1之間的混淆。

getchar()返回一個int與257個不同值中的一個:0到255和EOF。 EOF小於0(C11 7.21.1)。

通常 EOF的值爲-1,您的情況如此。讓我們假設以下。

有時,當從/dev/urandom讀取數據時,讀取值255。這是而不是的EOF。

鑑於OP執行char single_byte = getchar()single_byte呈現的(char) -1相同值,如果(int) -1(EOF)讀取或如果(int) 255讀取。

當未來比較single_byte != EOF,如果結果是false,我們不知道的getchar()原來的返回值是-1或255

推薦不同的printf()

printf("single_byte==EOF, so (int) 255 or EOF was read: 0x%hhx\n", single_byte); 

假設:
char是8位。
EOF是-1。

+0

當然,我知道;這就是OP被破壞的原因:有兩個字節重疊,程序在讀取一個隨機數字節後停止。 – giuscri

0
EOF values are 
EOF => %d => -1 
EOF => %c => <prints blank space but not blank space> 
EOF => %x => 0xFFFFFFFF 

對於EOF沒有ascii值!所以基本上你不能比較getchar()輸出和EOF。原因是當你離開空格並按回車時,空格的ASCII值爲0x20(十進制32),如果按回車,則回車的ASCII碼在0x0D中返回(十進制中的13)。

那麼這段代碼將無法使用!要麼你必須定義一個值來退出代碼!

+0

uhm ...所以你在說K&R中的EX1-6('驗證表達式'getchar()!= EOF'是'0'還是'1'')是壞的? – giuscri

+0

對不起!你的一段代碼是一個無限循環!當我輸入你的代碼段時,從來沒有工作意味着它永遠不會達到如果(single_byte == EOF)。 –

+0

對不起!你的一段代碼是一個無限循環!當我鍵入你的代碼段時,從來沒有工作意味着它永遠不會達到如果(single_byte == EOF),我應該明確我的錯誤。而且K&R中的EX1-6也不錯!直到你真的破壞了程序的執行,這是一個無限循環。在那個例子中,c的值總是1(總是!= 0)。 –