It's this way for historical reasons.
You can't reassign stdin
, stdout
, or stderr
. If you need to reopen these streams so they do their i/o somewhere else, that's what freopen
is for.
In the earliest implementations of <stdio.h>
, there was a global array
FILE _iobf[20];
and then stdin
, stdout
, and stderr
were, yes, macros:
#define stdin &_iobf[0]
#define stdout &_iobf[1]
#define stderr &_iobf[2]
This worked fine, and it was nice and compact. It looks "weird" to our eyes today — "Why would anyone have written it that way?", you might ask — but the point is that they did write it that way, and it stayed that way for many years, long enough that the C Standard had to accommodate it, by forbidding conforming programs from assigning new values to those "variables".
(To say a little more about "Why would anyone have written it that way?", I believe the answer is, economy. When <stdio.h>
was invented, C was brand-new, and the PDP-11 had a 64k address space, and you couldn't even always use all of it. Everybody did raw I/O using read()
and write()
, or implemented their own, special-purpose buffering schemes. Some people asked, "Why do we have to implement our own? Why isn't there a standard one?", while others said, "Everybody's needs are sightly different; no one implementation could satisfy everyone." It was a lot like the discussions we're still having today about why C doesn't have, say, a standard linked-list implementation. At some point Mike Lesk declared that he was going to implement a standard I/O library, that it was possible to come up with one implementation that would satisfy everyone's needs, or well enough. But to placate the naysayers, and to not inconvenience big programs that were already bumping up against the 64k ceiling, there was a huge incentive to keep the memory footprint — both code and data — minimal. I don't remember all the details, but that FILE _iobf[20];
scheme really did end up being pretty darn compact, and I'm guessing that any "obviously better" scheme you might come up with — that involved, say, dynamically allocating FILE structs rather than having a fixed array of 20 of them — would have a significantly larger memory footprint.)
#define stdout stdout
is kosher. The reason is most probably historical. For a long time (197x-200x), most systems used macros like#define stdin _ios[0]
(or possibly&_ios[0]
— the name was in the "reserved for the system" namespace). This meant that they could be used in file stream initializers at global scope (static FILE *err = stderr;
). GNU C Library changed their definition sometime in the 'oughts' and that's no longer possible. – Loellastdin
etc are also object identifiers, and if so, those identifiers will have either internal or external linkage. – Perfidyfreopen
to redirect the standard streams. – Oeuvre