5

Normally, C file I/O is done using FILE* as this is what the standard library functions all take.

In C, one can also have a const pointer, where the address of the pointer cannot change (but the value it points to can be).

I wondered if this could be applied to FILE*, so wrote this small program to test this:

#include <stdio.h>


int main(void) {
    FILE* const file = fopen("somefile.txt", "w");
    if (file != NULL) {
        fprintf(file, "%s\n", "So this works? That's just swell!");
    }
    return 0;
}

This compiles fine and works as intended on Ubuntu/Linux 16.04 using GCC (the file contains exactly the string I expected), but I'm not sure if this idiom is such a good idea —the FILE type is opaque by design and handling of it is implementation-specific.

Because there's no guarantee that any C library implementation won't try and change the address of the FILE pointer, is it safer to not use this approach when doing I/O in C?

saxbophone
  • 779
  • 1
  • 6
  • 22
  • This simply means that you can't change the value of `file`. It's entirely up to you whether that's useful. – Oliver Charlesworth Apr 21 '18 at 18:33
  • 2
    You've told the compiler that *your* code won't change the value of `file`. This has no effect on the standard library functions. Note that `FILE* const file` is different from `const FILE* file`. The latter says that what `FILE*` points to is `const`. In that case, you should get warnings from the compiler when you attempt to pass `file` to the standard library functions. – user3386109 Apr 21 '18 at 18:33
  • 2
    You can use `FILE * const` sanely; you cannot use `const FILE *` sanely. There's a guarantee that none of the functions in the C library will modify the pointer part of the `FILE *` you pass to them in any way detectable by the calling code, because the pointer is always passed by value — never the address of the pointer. So there is *no way* for the calling code to modify your pointer — unless it goes to insanely complex steps in order to do so, and it won't because there is neither any need nor any benefit to doing so,. – Jonathan Leffler Apr 21 '18 at 18:34
  • I'm aware of the difference between `FILE * const` and `const FILE *` (as well as why the latter doesn't make any sense). In my question I am seeking to clarify whether making the pointer `const` will have any negative impact on the standard library functions, as they don't take const pointers in their prototypes. – saxbophone Apr 21 '18 at 18:38
  • Also, for context of why I'm looking to do this —the same reasons why one might make any other pointer _const_: to stop an accidental re-assignment of what it points to! – saxbophone Apr 21 '18 at 18:39
  • 1
    It can't have any effect on the functions in the library; they are passed a copy of the value, and they won't modify the value, but won't be aware that the value is non-modifiable anyway, and won't care. Using `FILE * const fp = fopen(...);` simply means you can't reuse that file pointer for anything else in the same function, and you can't reset it to NULL after you `fclose()` it. Otherwise, it has no effect. I don't think it's useful; it isn't harmful except that it does nothing beneficial. – Jonathan Leffler Apr 21 '18 at 18:40
  • @JonathanLeffler aha! I didn't realise const pointers worked in that way when passed into functions. It looks like what you've written should maybe be the answer. – saxbophone Apr 21 '18 at 18:41
  • 1
    Standard functions that take `int` or `size_t` don't usually take a `const` but you can pass them the constant `0` no problem. Think why. – n. m. could be an AI Apr 21 '18 at 20:15

1 Answers1

6

Converting comments into an answer as requested.

You can use FILE * const sanely; you cannot use const FILE * sanely. There's a guarantee that none of the functions in the C library will modify the pointer part of the FILE * you pass to them in any way detectable by the calling code, because the pointer is always passed by value — never the address of the pointer. So there is no way for the calling code to modify your pointer — unless it goes to insanely complex steps in order to do so, and it won't because there is neither any need nor any benefit to doing so.

I'm aware of the difference between FILE * const and const FILE * (as well as why the latter doesn't make any sense). In my question I am seeking to clarify whether making the pointer const will have any negative impact on the standard library functions, as they don't take const pointers in their prototypes.

Also, for context of why I'm looking to do this — the same reasons why one might make any other pointer const: to stop an accidental re-assignment of what it points to.

It can't have any effect on the functions in the library; they are passed a copy of the value, and they won't modify the value, but won't be aware that the original value is non-modifiable anyway, and won't care. Using FILE * const fp = fopen(…); simply means you can't reuse that file pointer for anything else in the same function (or retry opening a different file name or calling a different 'open' function), and you can't reset it to NULL after you fclose() it. Of course, if the pointer goes out of scope because it is inside a loop, it can be reused when the scope is re-entered.

Otherwise, using FILE * const has no effect. I don't think it's useful. It isn't harmful except that it does nothing beneficial (and might confuse people). I recommend against using FILE * const.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278