3

Given the following short example

FILE *p = fopen("foo.txt", "r");
FILE f = *p;

int i;
fscanf(p, "%i", &i); // works just fine
fscanf(&f, "%i", &i); // segmentation fault

I have read a little about FILE, FILE * as well as the actual struct type _IO_FILE, but it isn't really clear to me what is causing the segmentation fault in the second call to fscanf.

So aside from p and &f containing different addresses and unless this is involved (which I think it is), what is the difference between &f and p in this context?

kzidane
  • 753
  • 3
  • 11
  • 29

2 Answers2

6

The C Standard (C99 7.19.3/6, C11 7.21.3/6) says:

The address of the FILE object used to control a stream may be significant; a copy of a FILE object need not serve in place of the original.

So you have been warned.

alk
  • 69,737
  • 10
  • 105
  • 255
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Got it! Anywhere I can find more information about this? Like the sense behind this having an undefined behavior rather than taking this for granted? – kzidane Dec 25 '14 at 20:37
  • 1
    The C standard and its rationale are good places to look (see [Where do I find the current C or C++ standard documents](http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents/83763#83763). [C: A Reference Manual](http://careferencemanual.com/) is another good source. – Jonathan Leffler Dec 25 '14 at 20:43
  • 2
    As of C11, `FILE` may be an incomplete type, so it might not even be possible to define a `FILE` object. C11 says `FILE` is an "object type"; C11 changed the definition of "object type" to include incomplete types. Note that `fpos_t` is required to be a "complete object type", so the change appears to have been deliberate. – Keith Thompson Dec 25 '14 at 21:22
0

You can consider FILE* as an opaque pointer sensu lato, you should never try to do what you are doing.

From cppreference.com:

C streams are objects of type std::FILE that can only be accessed and manipulated through pointers of type std::FILE* (Note: while it may be possible to create a local object of type std::FILE by dereferencing and copying a valid std::FILE*, using the address of such copy in the I/O functions is undefined behavior).

Jack
  • 131,802
  • 30
  • 241
  • 343