Search code examples
cfilepointersmemory-addressfile-pointer

Why file pointer acts different from normal pointer in C language?


Here's my C code:

#include"stdio.h"
#include"stdlib.h"
#include"string.h"
#include"limits.h"

int main(int argc,char **argv){
    int Array[2]={100,150};
    int *pArray=Array;
    int *qArray=pArray;
    qArray++;

    printf("pArray address:%p\n",pArray);
    printf("qArray address:%p\n",qArray);

    if(pArray!=qArray){
        printf("pArray not equals to qArray\n\n");
    }

    FILE *fp1=NULL,
         *fp2=NULL,
         *fp3=NULL,
         *fp4=NULL,
         *fp5=NULL;

    fp1=fopen("test.bin","rb+");
    if(fp1==NULL){
        return 1;
    }

    fp2=fp1;
    fp3=fp1;
    fp4=fp1;
    fp5=fp1;

    fseek(fp2,100l,SEEK_CUR);
    fseek(fp3,200l,SEEK_CUR);
    fseek(fp4,300l,SEEK_CUR);
    fseek(fp5,400l,SEEK_CUR);

    printf("fp1 position:%lu\n",ftell(fp1));
    printf("fp2 position:%lu\n",ftell(fp2));
    printf("fp3 position:%lu\n",ftell(fp3));
    printf("fp4 position:%lu\n",ftell(fp4));
    printf("fp5 position:%lu\n",ftell(fp5));

    if(fp1==fp5){
        printf("fp1 equals to fp5.\n");
    }

    fclose(fp1);
    return 0;
}

And this is the output:

$ ./program 
pArray address:0x7ffe5e6780a0
qArray address:0x7ffe5e6780a4
pArray not equals to qArray

fp1 position:1000
fp2 position:1000
fp3 position:1000
fp4 position:1000
fp5 position:1000
fp1 equals to fp5.

I made a conclusion: Moving a normal pointer does not affect the pointer that share address with it, but moving a file pointer with fseek function, however, does affect.

Why file pointer acts different from normal pointer?


Solution

  • A FILE * is not a pointer to a file; it is a pointer to a FILE. Per C 2018 7.21.1 2, a FILE is:

    … an object type capable of recording all the information needed to control a stream, including its file position indicator, a pointer to its associated buffer (if any), an error indicator that records whether a read/write error has occurred, and an end-of-file indicator that records whether the end of the file has been reached…

    Thus fp2=fp1; makes fp2 point to the same object that is used to control the file, so any changes made to the object pointed to by fp1 appear in the object pointed to by fp2 and vice-versa because they are the same object.

    qArray++ changes the pointer qArray. fseek(fp2,100l,SEEK_CUR); changes the object pointed to by fp2 (and the stream it controls). Similarly, if you called some routine ChangeAnElementInArray(qArray, index, value), that would change an element in the array; it would not change the qArray pointer.

    Also, a FILE * is not a position in a file. It is just a pointer to the data structure that is used to control the stream.