1

Here is the code:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    FILE* fp = fopen("sample.txt", "w");

    if (fp == NULL)
        return 1;

    int error = 0;

    if ((error = fseek(fp, -5, SEEK_END)) != 0)
    {
        printf("Error fseek failed: %d\n", error);
        fclose(fp);
        return 1;
    }

    fprintf(fp, "%d", 1);
    fclose(fp);
    return 0;
}

My sample.txt file:

adsfasdfasdfasfasfasfasdfasfasfasfas
asdfasdfasdfasdfasfadsfsadfadsfsafad

In the above program fseek return -1 and makes the file blank and same with "w+" mode. The same program works in "r+" correctly. I want to know what is the relation between fseek and file modes in C language? I try to search but I found nothing on the web till now.

2 Answers2

3

The fopen modes "w" and "w+" will delete the content of the fle, if it exists, so that you will have a new file with a length of zero. The mode "r+" will not do this, but will keep any existing file content.

All of this is stated in the documentation for fopen.

If the file has a length of zero, then the function call

fseek(fp, -5, SEEK_END)

will fail, because there is no such offset.

Also, it is also worth noting that according to §7.21.9.2 ¶4 of the ISO C11 standard, that function call to fseek will invoke undefined behavior. When a file is opened in text mode (as you have done), the only permissible offset for fseek is the value 0 or the previous return value of a function call to ftell. This is especially a problem on Microsoft Windows, because it uses \r\n at the end of every line, which gets translated to \n in text mode. However, this is not a problem on POSIX platforms which do not distinguish between text mode and binary mode. POSIX platforms always use \n in both modes.

This rule is also mentioned in the documentation for fseek.

However, in practice, it probably won't be a problem to use fseek with a non-zero offset in text mode, as long as you don't jump into the offset between a \r and an \n character, and if you take into account that on Windows, a \r\n line ending counts as two offsets, even though \r\n gets translated to \n in text mode.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • While my focus was on fseek I completely forgot about `w` and `w+` mode will create new file as soon as it processes `fopen`. You have solved most of my query about this. Still I wanted to know the relation between file mode and `fseek`. Thanks. – Rakesh Solanki May 20 '23 at 15:41
  • @RakeshSolanki: You can use `fseek` in all `fopen` modes. However, there are certain rules. I have already mentioned one rule in my answer. Another rule is that when a file is opened in update mode (i.e. the mode contains a `+`, such as `"r+"`), then you may have to use `fseek` (or another file positioning function) before writing after a read, and vice versa. See [this question](https://stackoverflow.com/q/76245752/12149471) for more information on that rule. – Andreas Wenzel May 20 '23 at 15:49
1

Replace printf("Error fseek failed: %d\n", error); with perror("fseek"); and it'll likely print fseek: Invalid argument or similar.

You truncate the file by opening it with "w" and they try to go back 5 characters from the end (in an empty file). In a normal file, that can't be done.

When opening it with "r+" the content of the file is preserved and seeking backwards from the end 5 steps succeeds (with the content you've shown).

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108