Actual assignment of stdin, stdout and stderr to standard input and standard output

603 views Asked by At

I am going through K&R. I am bit confused with the following excerpt of stdio.h.

typedef struct _iobuf {
  int cnt;    /* characters left */
  char *ptr;  /* next character position */
  char *base; /* location of buffer */
  int flag;   /* mode of file access */
  int fd;     /* file descriptor */
} FILE;

extern FILE _iob[OPEN_MAX];

#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])

Here the FILE is defined as a structure, and the stdin, stdout, stderrare first three member of an array of type FILE. So where is the assignment of (&_iob[0]), (&_iob[1]) or (&_iob[2]) to standard input deviceand standard output device are written?

4

There are 4 answers

2
Chinna On

Here, _iob[OPEN_MAX]; is declared as extern variable as extern FILE _iob[OPEN_MAX];. This means, _iob[OPEN_MAX]; is filled by some other code and there is an initial code which assigns (&_iob[0]), (&_iob[1]) or (&_iob[2]) to stdin, stdout and stderr

0
glglgl On

This assignment is probably conducted by some initialization code which runs before main().

This code is - among other things - supposed to link these array entries to their respective file descriptors, which are already open by the OS's loader.

0
harvis On

You can try a method. Under windows, I use llvm-ojbdump search _iob related symbol.

llvm-objdmp -t libucrt.lib > symbol.txt

find keyword '_iob' in file symbol.txt, I found symbol __acrt_iob_func, then construct piece code for verification.

extern FILE* __acrt_iob_func(unsigned);
#define stdin  (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))

You can use other tools to dump symbol of C library then search symbol you needed.

0
daltonvlm On

I know this question was made in 2013. Probably, the author of it already knows the answer. But, since the topic is open by the missing of a checked correct answer, I will leave my view here.

I think that, even with the reimplementation of some io functions, the association between the devices stdin, stdout and stderr by the system (Unix) with the file descriptors continues untouched.

So, I think this piece taken by the book is the answer to the question:

FILE _iob[OPEN_MAX] =  { /* stdin, stdout, stderr : */
{ 0, (char *) 0, (char *) 0, _READ, 0 },
{ 0, (char *) 0, (char *) 0, _WRITE, 1 },
{ 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2 }};

Every time a read or write function occurs, these file descriptors will be passed to them. And, since these functions (the read and write) are not reimplemented, the system knows where to connect with those file descriptors.