2015-08-21 106 views
1

當閱讀K & R時,我開始對如何確定文件位置感興趣。按照文件位置,我指的是流正在讀取或寫入的文件的位置。我認爲它必須與文件指針或它指向的數據有關。所以,我檢查堆棧溢出,並找到以下答案:文件指針會隨着文件位置的變化而移動嗎?

Does fread move the file pointer?

答案表明,文件指針會隨着文件位置的改變而改變。這讓我非常困惑,因爲在我的理解中,某個文件的文件指針應該始終指向相同的地址,這裏存儲着關於這個文件的信息。所以我寫了一小段代碼,試圖找到答案:

#include<stdio.h> 
int main(void) 
{ 
    char s[1000]; 
    FILE *fp,*fp1,*fp2; 
    fp = fopen("input","r"); 
    fp1 = fp; /* File poiter before fread */ 
    fread(s,sizeof(char),100,fp); 
    fp2 = fp; /* File pointer after fread */ 
    printf("%d\n",(fp1 == fp2) ? 1 : -1); 
} 

它給人的輸出1,我相信指示文件指針居然不動,並仍然指向相同的地址。我也改變了fread行爲fseek,它給出了相同的輸出。那麼文件指針會隨着文件位置的變化而移動,或者我在驗證過程中錯在哪裏?

謝謝!

+0

Nooo ....當然你明白,文件系統需要的不僅僅是一些指針,它可以控制對文件的訪問! FILE *'文件指針'通常是文件控制塊的基地址 - 關於該文件的整個元數據結構。 –

+0

你似乎混淆了'文件* fp',它指向(在fopen()調用之後)'文件描述符'控制塊到'文件描述符'控制塊內的數據,指示當前設備,柱面, (一般情況下)硬盤上的磁道,扇區等。 – user3629249

回答

5

我認爲你混淆了C中指針的一般概念,而不是「文件指針」的命名。 FILE只是一個包含大多數「內務」屬性的結構,當使用stdio函數(如fopen(),fread()等)時,C stdio運行時庫需要與之交互。下面是一個結構示例:

typedef struct { 
char *fpos; /* Current position of file pointer (absolute address) */ 
void *base; /* Pointer to the base of the file */ 
unsigned short handle; /* File handle */ 
short flags; /* Flags (see FileFlags) */ 
short unget; /* 1-byte buffer for ungetc (b15=1 if non-empty) */ 
unsigned long alloc; /* Number of currently allocated bytes for the file */ 
unsigned short buffincrement; /* Number of bytes allocated at once */ 
} FILE; 

請注意,這可能與平臺有關,所以不要把它當作福音。因此,當您調用fopen()時,底層庫函數將與O/S的文件系統API進行交互,並在此結構中緩存關於文件,緩衝區分配等的相關信息。 fopen()函數爲該結構分配內存,然後以C指針的形式將該內存的地址返回給調用者。

將指針值賦給另一個指針對FILE結構中的屬性沒有影響。但是,FILE結構在內部可能具有指向底層O/S文件的索引或「指針」。因此,術語混淆。希望有所幫助。

+0

非常感謝!我也在想這可能只是一個術語問題。你的回答很清楚。 –

1

你是對的fp從不改變fread,fseek或其他f...功能。當然,除了你做fp = fopen(...),但是你當然將fopen的返回值分配給fp,然後fp改變。

請記住,在C參數中按值傳遞,因此fread不能更改它的值。

fread的確改變了內部結構fp指向。

+0

甚至不能保證改變結構:有些實現可能只是使用POSIX風格的文件描述符搭載在較低級別的文件API上,並且只將描述符放在結構中(儘管它可能會降低性能) 。 – Medinoc

+1

@Medinoc是正確的,但無論如何,沒有人應該關心。 –

+0

謝謝。 「按價值傳遞」的評論確實令人信服。 –

1

您在公共定義下的文件指針和文件中的指針之間存在一些混淆。 正常情況下,術語文件指針我們指的是指向結構的指針。該結構包含管理文件訪問所需的全部變量。該結構是在成功打開文件時創建的,並且始終保持相同(相同的地址),直到文件fclose()(變爲未定義)爲止。

在FILE結構中有很多指針指向磁盤上的文件塊和當前記錄內的位置。這些由文件I/O例程管理的指針在訪問文件(讀或寫)時發生變化。 這些指針是你引用的答案所引用的。

+0

所以你的意思是文件的位置是由FILE結構中的指針決定的?但是如果只有一個描述符,這怎麼能工作呢?我的意思是,如果打開一個文件時系統調用open()而不是庫例程打開,那麼就沒有FILE結構這樣的事情。在這種情況下,檔案的位置仍然應該確定,並可以通過像lseek這樣的功能來改變。 –

+0

@AlbertZhou文件控制結構很多。操作系統驅動程序中的第一級負責使用磁盤原始塊,下一級位於文件系統驅動程序中,其中原始數據在目錄和文件中組織。在那之上有所謂的低級I/O(而open()是低級別的),它有自己的控制結構。然後是使用FILE結構的高級I/O。 'fopen()'使用FILE結構,它使用使用原始I/O的文件系統的低級I/O。生活並不容易;-) –

+0

@AlbertZhou我忘記了一個文件描述符是低級I/O例程使用的文件控制結構數組的索引。所以有數據不僅有一個'描述符'... –