Daros
Daros

Reputation: 59

Fflush on a file

Having simple code from a cplusplus.com site

#include <stdio.h>

char mybuffer[80];

int main() {
    FILE *pFile;
    pFile = fopen("example.txt","r+");
    if (pFile == NULL)
        perror("Error opening file");
    else {
        fputs("test",pFile);
        fflush(pFile);    // flushing or repositioning required
        fgets(mybuffer, 80, pFile);
        puts(mybuffer);
        fclose(pFile);
        return 0;
    }
}

I'm wondering what fflush really does in case of file as its argument like in the above code because the result is the same with and without the fflush(pFile) line - en empty buffer (nothing on the output).

PS: I'm running the code on Linux gcc (6.3.0)

Upvotes: 2

Views: 1164

Answers (2)

chqrlie
chqrlie

Reputation: 144770

From the C18 Standard:

7.21.5.3 the fopen function

Synopsis

#nclude <stdio.h>
FILE *fopen(const char * restrict filename,
            const char * restrict mode);          

Description

...

7 When a file is opened with update mode (+ as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations.

Here are the steps performed by the posted code

  • the file example.txt is opened in read and update mode.

  • 4 bytes (text) are written to the file, overwriting the first 4 bytes of the file.

  • the stream buffer is flushed with fflush(), allowing a mode change from writing to reading. This is what the comment refers to: // flushing or repositioning required

  • the program switches to read mode without a position change and tries to read up to 79 bytes from position 4 in the file, stopping at a newline. If no bytes can be read, NULL is returned.

  • this line is output to standard output. Note however that if the file contained 4 bytes or less, fgets(mybuffer, 80, pFile) fails and returns NULL, leaving the array mybuffer in an undetermined state, causing puts(mybuffer); to have undefined behavior.

  • the file is closed

Upvotes: 5

Barmar
Barmar

Reputation: 781058

fflush() normally isn't needed when you're reading and writing the same stdio stream. fputs() and fgets() both access the same I/O buffer, so flushing isn't usually necessary in this case.

There are some restrictions, though. Even though the same buffer is used, you have to do something to synchronize between writing and reading. This can be fflush(), but it will also synchronize if you use fseek(). And if you want to read what you just wrote, you have to use fseek() to move back to the place where you started writing; that will synchronize without the need for fflush().

But fflush() is really needed if some other process tries to read the file while this process is writing it. You need to call fflush() to force the data from your I/O buffer to the actual file, so the other process will see the changes.

Upvotes: 0

Related Questions