2012-06-15 52 views
9

在書中的Linux系統編程我看過一些這樣的:龜etc,檢查EOF

fgetc解讀爲unsigned char投人物返回到文件或錯誤的前端部的intEOF。使用fgetc一個常見的錯誤是:

char c; 
if ((c = fgetc()) != EOF) {...} 

這段代碼的正確版本是:

int c; 
if ((c = fgetc()) != EOF) { printf("%c", (char)c); ... } 

那麼,爲什麼我不能用EOF比較之前投下了返回值char?爲什麼我必須比較EOFint?由於EOF定義爲-1,是不是通常鑄造成char
有沒有平臺/編譯器不正確?

+0

[「while(!feof(file))」的可能重複始終是錯誤的](http://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) – jww

+0

@jww:這個問題沒有使用'feof()',所以它不是'['while(!feof(file))''總是錯誤]的重複(http://stackoverflow.com/questions/5431941/while-feof-文件是 - 總是錯的)」。 –

回答

10

您不能將返回值轉換爲char,因爲返回值可能是EOF,而EOF值是系統相關的並且不等於任何有效的字符代碼。 link

通常它是-1但您不應該這樣假設。

檢查從c-faq-site這個偉大的回答:如果在上面的片段的getchar的 返回值被分配給一個char

兩種失效模式是可能的。

  1. 如果類型炭被簽名,並且如果EOF定義(像通常那樣),爲-1時, 字符與十進制值255(「\ 377」或「\ XFF」在C)將 符號擴展並將比較等於EOF,提前終止輸入 。 (假設8位字符)。

  2. 如果類型char是無符號的,實際的EOF值將被截斷(由 具有其高位比特丟棄,可能導致255或 0xff的),並且將不會被識別爲EOF,從而導致有效地 無限輸入。

希望它能幫助!

編輯:(加入這個答案@FatalError評論,這是在C-FAQ網站解釋,但這看起來更清楚地知道)

「如果你將它轉換成char然後EOF取與某個有效字符相同的值,因此與該字符無法區分。僅憑這一點就足以證明不會產生字符「@FatalError註釋」。

+0

等等呢?我不明白。鑄造char後將等於'-1',不是嗎? – pproger

+0

我的字符不是無符號的,我給你的代碼示例。 – pproger

+0

@pproger這個標準實際上並不強制'char'是單獨簽署還是未簽名。如果你想保證有符號的字符,你必須使用'signed char'。 – Corbin

3

有兩種可能性,當你與EOF比較之前將值賦給一個char

  • char是一個符號值。在這種情況下,有一個合法的字符(通常是ÿ,帶有DIAERESIS的小型拉丁字母U + 00FF),將被誤解爲EOF。
  • char是一個無符號值。在這種情況下,EOF將被轉換爲0xFF,然後被提升爲int作爲正值,該值永遠不會等於負值的EOF。

無論哪種方式,該計劃都會在某些時候行爲不端。

存在(或更準確地說,曾經是)編譯器錯誤的機會,使得分配正確發生,但分配的值未用於比較。這會導致代碼出現工作正常,即使它不是。幸運的是,這在現代編譯器中不太可能成爲問題。