ncurses' curses.h
includes <stdio.h>
because a few of the (X/Open Curses) standard functions which curses.h
declares use FILE
. The C standard refers to FILE
as an "object type", which some might read literally as requiring a typedef
. However there have been implementations where FILE
is a symbol defined with #define
, e.g.,
#define FILE struct _iobuf
(quoting from more than one BSD: 4.3BSD, SunOS 4, Ultrix). Without delving into its history, I'd assume the change to make it a typedef
came from the AT&T code since it shows up in the SVr4 implementations.
For that reason (as well as it being the simplest way to guarantee that FILE
is declared properly), curses.h
will include stdio.h
.
Now... there are a few other header files which you might encounter which require another header file to be included, to make them useful. One longstanding example is for the stat
function, i.e.,
#include <sys/types.h>
#include <sys/stat.h>
but in the relevant (system-specific) documentation, both headers are shown in the manual page summary. The POSIX documentation for stat
does not point that out, but uses it in the examples. Some newer implementations include (or provide in some roundabout way) the definitions from <sys/types.h>
needed in <sys/stat.h>
, but in writing portable code, that has not been something to rely upon.
curses was never documented in that way, e.g., you're unlikely to find manual pages showing
#include <stdio.h>
#include <curses.h>
because the original 4BSD curses included <stdio.h>
. Interestingly enough, 4.2BSD curses header did not use any definition from stdio.h
. It also included sgtty.h
(analogous to termios.h
), but used those definitions in the header file. Perhaps the original developer thought that including stdio.h
was a good idea. In any case, in later versions of curses, it did use FILE
, and since the precedent of including stdio.h.
from curses.h
was well established, no one considered splitting things up as done with <sys/types.h>
and <sys/stat.h>
.
ncurses' documentation has mentioned the header files which curses.h
includes, in a NOTES section:
The header file <curses.h>
automatically includes the header files
<stdio.h>
and <unctrl.h>
.
That note dates back to ncurses 1.8.7 in 1994, making it rather unlikely that you will encounter a version of ncurses for which the statement is untrue.
X/Open Curses has something similar to say:
The inclusion of <curses.h>
may make visible all symbols from the headers <stdio.h>
, <term.h>
, <termios.h>
and <wchar.h>
.
HPUX curses, for instance, includes <term.h>
from <curses.h>
to declare setupterm
in curses.h
, but ncurses (and Solaris curses) do not. AIX curses includes <term.h>
and <termios.h>
. Again, ncurses (and Solaris curses) do not. X/Open Curses says "may make visible" because including a header file does not necessarily make all symbols in it visible (there are ifdef's to consider).
However, these functions in any X/Open Curses (i.e., anything more current than 1990) use FILE
, making <stdio.h>
needed for <curses.h>
:
Now... including <stdio.h>
before <curses.h>
probably will not make any difference (aside from adding clutter to your program). It's possible (but unlikely) that there could be some symbol redefined in <curses.h>
which alters the behavior of the standard features in <stdio.h>
. Since any implementation of stdio.h
which you are likely to encounter has include-guards (a feature from the 1990s—not seen in SunOS 4's 1994 headers) including <stdio.h>
after <curses.h>
would also be unlikely to change the behavior of your program (again, clutter being the only result).
Include-guards have been the preferred style for system headers since the 1990s. I have a script (called Include
) which I use for test-compiling headers which I wrote in 1998, to check that a given header includes the necessary headers (such as in this case) to provide all of the necessary typedefs and symbols used in the header file.