Lokesh Jaddu
Lokesh Jaddu

Reputation: 53

File pointers behave differently when passed to functions. Why?

So i have this code

void getdata(int *q)
{
   for(int i=0;i<3;++i)
      scanf("%d",q++);
   *q=10;
}

int main()
{
   int *p,a[4];
   p=a;
   getdata(p);
   printf("%d",*p);
   return 0;
}

And the output is obvious.

7
8
9
7

But file pointers dont work the same way. I was trying to write a basic code for appending data into a file.

void getdata(FILE *fp)
{
    char ch;
    while((ch=getchar())!=EOF)
        fputc(ch,fp);
    rewind(fp);
}

void printdata(FILE *fp)
{
    char ch;
    while((ch=fgetc(fp))!=EOF)
        putc(ch,stdout);
}
int main()
{
    FILE *fp1;
    fp1=fopen("music.txt","w+");
    getdata(fp1);
    printf("Text is::\n");
    printdata(fp1);
    fp1=fopen("music.txt","a+");
    printf("\nEnter some more text::\n");
    getdata(fp1);
    printf("\nAfter appending text is::\n");
    printdata(fp1);
    return 0;
}

This code works fine. But if rewind(fp); is removed it acts weird. Why do i need to rewind the pointer? Though pointing to the same file aren't fp1 and fp local to the function and so shouldn't affect each other as in the first program?

Upvotes: 2

Views: 728

Answers (3)

Nishant
Nishant

Reputation: 2619

Other answers explain it more technically, so I will keep it simple.

First understand the following

  • fp is like a head pointer. It is moved forward on each read of write operation, so that next read or write into the file will start from the end of previous operation.
  • Since it is a pointer, hence whenever it is changed (in a function or in main) the changes will be reflected everywhere.
  • Rewind sets the fp to the start of the file

So in this example, when you write into the file using getdata, fp(or the head) moves forward after writing each character, i.e. always remains at the end of the file. Then rewind is done to bring it back to the head of the file. Hence when you print again, reading starts from the start of the file and not from end of file.

Now, if you do not rewind then fp will remain at the end of file and printdata will not print any thing.

Upvotes: 0

theadnangondal
theadnangondal

Reputation: 1664

enter image description hereAny process which opens a files has a data structure which stores the seek position etc related to a file . no matter how many times you open same file it is a pointer to the same DS. Print the values of both File pointer's it should be same... So it does not matter with which File * you are accessing the file . they will effect each other working ...

nice practise is to have 1 FP to 1 file ... if you need another one close the previous

As open files counts as resources to a process. So this is more related to process resources then locality

Upvotes: 0

mtijanic
mtijanic

Reputation: 2902

Let's look at a possible very simplified implementation of FILE structure. For the purpose of the example, assume content points to a memory that's mapped to a file on the disk..

typedef struct FILE {
    size_t size;
    size_t cursor;
    uint8_t *content;
} FILE;

int fputc(FILE *f, char c) { size++; return f->content[f->cursor++] = c; }
int fgetc(FILE *f) { return (f->cursor == f->size) ? EOF : f->content[f->cursor++]; }
void rewind(FILE *f) { f->cursor = 0; }

Now when you call these functions, it is obvious they modify the underlying object. When you are done writing to the file, cursor points to the last element, so fgetc will return EOF immediately if you don't rewind.


To clarify, when you call fopen you create a single FILE object that is stored somewhere. You have no control over this object, you just get a pointer to it. You can consider this pointer (fp1 in your example) as a file ID if it is easier to understand. Any changes are done on the FILE object, not the pointer/ID itself.

Upvotes: 2

Related Questions