while (fread(&product, sizeof(Product), 1, file) == 1) {
product.price *= 2.0;
fseek(file, -sizeof(Product), SEEK_CUR);
fwrite(&product, sizeof(Product), 1, file);
fseek(file, 0, SEEK_CUR);
}
Using the code above, I tried to double the price of each product in the binary file, where each record is an instance of a Product struct. When I ran this code, it updated all the prices in the file correctly.
As far as I know, fread
automatically moves the file pointer to the next record. Using the first fseek
, the code moves the file pointer back to the beginning of the record. Then it updates it using fwrite
. fwrite
automatically moves the file pointer to the next record. In the while loop, fread
should continue to read the next record, and so on.
It seems that fseek(file, 0, SEEK_CUR);
is unnecessary here. However, if I remove it, the code enters an infinite loop. I cannot figure out why this happens.
I tried to observe the value of file pointer using ftell
. But I did not see any change its value after fseek(file, 0, SEEK_CUR);
.
When a stream is opened for both reading and writing, you are not allowed to directly switch between reading and writing. §7.21.5.3 ¶7 of the ISO C11 standard states the following:
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.
If you remove the line
fseek(file, 0, SEEK_CUR);
then your program violates this rule, which invokes undefined behavior. This means that anything can happen, which includes the possibility of your program getting stuck in an infinite loop.