C語言中文網 目錄

EOF宏,C語言EOF宏詳解

EOF 是 End Of File 的縮寫,在 C 語言標準庫中的定義如下:

#define  EOF  (-1)

迄今為止,關于 EOF 作用的觀點各異。大多數程序員認為“文件中有一個 EOF 字符,用于表示文件的結尾”。但實際上,這個觀點并不正確(或者說并不完整),在文件所包含的數據中,并沒有什么文件結束符。從 EOF 宏的定義中可以看出,EOF 宏的值為 -1,屬于 int 類型的數據,在 32 位系統中,可以表示為 0xFFFFFFFF。由此可見,EOF 并不是一個字符,也不是文件中實際存在的內容。那么,為什么會有這樣的觀點存在呢?

其實原因很簡單,因為對一些數據讀取函數(如 fgetc 與 getc 函數)而言,如果讀到文件末尾(也可以理解為“如果不能從文件中讀取”,即文件已經讀完或者文件讀取出錯),則返回一個整數(-1),這就是所謂的 EOF。因此,EOF 宏不但能夠表示讀文件到了結尾這一狀態(這種狀態可以用 feof() 來檢測),還能表示 I/O 操作中的讀、寫錯誤(通常可以用 ferror() 來檢測)以及其他一些關聯操作的錯誤狀態。

看下面這段示例代碼:
int main(void)
{
    FILE *fp=NULL;
    int c;
    fp=fopen("myfile.txt","r");
    if(fp == NULL)
    {
        printf("不能夠訪問該文件.\n");
        exit(1);
    }
    while((c=fgetc(fp)) != EOF)
    {
        printf("%x\n", c);
    }
    fclose(fp);
    fp=NULL;
}
對于 fgetc(或者 getc)函數,它返回一個 int 類型的數據。在正常情況下,fgetc(或者 getc)函數以 unsigned char 的方式讀取文件流,并擴張為一個整數返回。換言之,fgetc(或 getc)函數從文件流中讀取一個字節,并加上 24 個 0,成為一個小于 256 的整數,然后返回。

對于上面的示例代碼,在正常讀取的情況下,fgetc 函數返回的整數均小于 256(即 0x0~0xFF)。因此,就算讀到了字符 0xFF,由于變量 c 被定義為 int 型,實際上這里的 c 等于 0x000000FF,而不是等于 EOF(即 0xFFFFFFFF),當然也不會誤判為文件結尾。也就是說,即使是上面的示例代碼遇到字符 0xFF,while 循環也不會結束,因為 0xFF 會被轉化 0x000000FF,而不是 0xFFFFFFFF(EOF)。

既然如此,如果這里把 c 定義為 char 類型,那么其結果又將會怎樣呢?如下面的示例代碼所示:
char c;
fp=fopen("myfile.txt","r");
if(fp == NULL)
{
    printf("不能夠訪問該文件.\n");
    exit(1);
}
while((c=fgetc(fp)) != EOF)
{
    printf("%x\n", c);
}
因為文本文件中存儲的是 ASCII 碼,而 ASCII 碼中 FF 代表空值(blank),所以如果讀文件返回了 0xFF,也就說明已經到了文本文件的結尾處。也就是說,在語句“while((c=fgetc(fp))!=EOF)”中,當讀取的字符為 0xFF 時,子語句“c=fgetc(fp)”中的“fgetc(fp)”的值由 0x000000FF 轉換為 char 類型(即 c 等于 0xFF);而在執行子語句“c!=EOF”時,字符與整數比較,c 被轉換為 0xFFFFFFFF,條件成立,遇到空格字符時就退出。由此可見,如果是二進制文件,其中可能會包含許多 0xFF,因此不能把讀到 EOF 作為文件結束的條件,而此時只能使用 feof() 函數。

再假如,這里又將 c 定義為 unsigned char 類型,結果會與上面的 char 類型相同嗎?如下面的示例代碼所示:
unsigned char c;
fp=fopen("myfile.txt","r");
if(fp == NULL)
{
    printf("不能夠訪問該文件.\n");
    exit(1);
}
while((c=fgetc(fp))!= EOF)
{
    printf("%x\n", c);
}
在上面的“while((c=fgetc(fp))!=EOF)”語句中,就算是語句“fgetc(fp)”返回的結果為 -1(即 0xFFFFFFFF),但通過語句“c=fgetc(fp)”對其強制轉換 unsigned char 類型,即 c 等于 0xFF。而在執行子語句“c!=EOF”時,c 被轉換成 0x000000FF,永遠也不可能等于 0xFFFFFFFF,因此表達式“c!=EOF”將永遠成立。

由此可見,只有將 c 定義成 int 類型的變量,才能夠與 fgetc 函數返回類型一致。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo