abhishek_M
abhishek_M

Reputation: 1170

What happens when we dereference a FILE pointer?

Suppose I have a file pointer

FILE* infile = fopen("<somefilepath", "r");

Now when I dereference the file pointer in gdb then I get

print *infile

│$2 = {_flags = -72539000, _IO_read_ptr = 0x0, _IO_read_end = 0x0,
│ _IO_read_base = 0x0, _IO_write_base = 0x0, _IO_write_ptr = 0x0,
│ _IO_write_end = 0x0, _IO_buf_base = 0x0, _IO_buf_end = 0x0,
│ _IO_save_base = 0x0, _IO_backup_base = 0x0, _IO_save_end = 0x0, _markers = 0x0,
│ _chain = 0x7ffff7dd41c0 <_IO_2_1_stderr_>, _fileno = 3, _flags2 = 0,
│ _old_offset = 0, _cur_column = 0, _vtable_offset = 0 '\000', _shortbuf = "",
│ _lock = 0x6020f0, _offset = -1, __pad1 = 0x0, __pad2 = 0x602100, __pad3 = 0x0,
│ __pad4 = 0x0, __pad5 = 0, _mode = 0, _unused2 = '\000' }

Can someone help me understand what this means ?

Upvotes: 0

Views: 2142

Answers (3)

user5321364
user5321364

Reputation: 1

FILE is described in the C standard, section 7.21.1:

2 The types declared are size_t (described in 7.19);

    FILE

which is an object type capable of recording all the information needed to control a stream, including its file position indicator, a pointer to its associated buffer (if any), an error indicator that records whether a read/write error has occurred, and an end-of-file indicator that records whether the end of the file has been reached; ...

In your particular instance, it seems you are using glibc. It's implementation of FILE can found in libio.h:

struct _IO_FILE {
  int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */

  struct _IO_marker *_markers;

  struct _IO_FILE *_chain;

  int _fileno;
#if 0
  int _blksize;
#else
  int _flags2;
#endif
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];

  /*  char* _save_gptr;  char* _save_egptr; */

  _IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};

Keep in mind the full implementation spans many files, functions, data structures, etc.

Upvotes: -1

Columbo
Columbo

Reputation: 60979

C11 7.21.1/2 describes FILE as

…an object type capable of recording all the information needed to control a stream, including its file position indicator,a pointer to its associated buffer (if any), an error indicator that records whether a read/write error has occurred, and an end-of-file indicator that records whether the end of the file has been reached;

But doesn't mention specific members. Here is glibc's implementation that you observed (I deleted unused preprocessor branches for clarity):

struct _IO_FILE {
  int _flags;       /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

  /* The following pointers correspond to the C++ streambuf protocol. */
  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
  char* _IO_read_ptr;   /* Current read pointer */
  char* _IO_read_end;   /* End of get area. */
  char* _IO_read_base;  /* Start of putback+get area. */
  char* _IO_write_base; /* Start of put area. */
  char* _IO_write_ptr;  /* Current put pointer. */
  char* _IO_write_end;  /* End of put area. */
  char* _IO_buf_base;   /* Start of reserve area. */
  char* _IO_buf_end;    /* End of reserve area. */
  /* The following fields are used to support backing up and undo. */
  char *_IO_save_base; /* Pointer to start of non-current get area. */
  char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  char *_IO_save_end; /* Pointer to end of non-current get area. */

  struct _IO_marker *_markers;

  struct _IO_FILE *_chain;

  int _fileno;
  int _flags2;
  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */

#define __HAVE_COLUMN /* temporary */
  /* 1+column number of pbase(); 0 is unknown. */
  unsigned short _cur_column;
  signed char _vtable_offset;
  char _shortbuf[1];

  /*  char* _save_gptr;  char* _save_egptr; */

  _IO_lock_t *_lock;

  _IO_off64_t _offset;
  void *__pad1;
  void *__pad2;
  void *__pad3;
  void *__pad4;
  size_t __pad5;
  int _mode;
  /* Make sure we don't get into trouble again.  */
  char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
};

Upvotes: 4

mark
mark

Reputation: 5469

FILE * should be considered an opaque value... Dereferencing it will be platform/library-dependent (and thus not portable).

Upvotes: 6

Related Questions