I have two files foo.c and bar.c that I compile separately with gcc -c
and then link. Both files need the stdio.h and stdlib.h headers.
Do I have to in
Each C file is a different translation unit. In other words, it is an entire separate program, syntactically complete and correct. Thus, each C file must compile independently of any other C file, and must contain every declaration for every identifier it uses, regardless of whether these declarations also appear in other C files. From the compiler point of view, each C file is a complete program by itself (albeit with unresolved references).
Header files are, by convention, files that contains declarations that must appear in a group of C files. Header files can be included by the preprocessor -- which is a simple textual copy-and-paste at the include point -- as a convenience to avoid manually duplicating declarations between the translation units.
Summing up: it is not redundant to include the same files in different C files -- it is formally required.
(Afterwards, you link object files, which are just smaller programs, into a larger final program. The larger program is roughly a summation of smaller subprograms, with all references resolved between them. Generally speaking, the linking phase does not know anything about the language structure of the original files that generated the resulting object file.)
You must include your header with both files. The header is just a list of function declarations and constant declarations. The compiler needs these to make sure your syntax and function calls are correct.
The header file should (and will) have a #ifndef wrapper to prevent problems with this (the problem is actually with cyclic inclusion - you include -> foo.h includes bar.h bar.h includes foo.h).
In your case the "duplicate" inclusion is actually needed (for function prototypes, structure definitions) since (as you said) both files are compiled separately. The compile process of foo.c doesn't know anything about the compilation of bar.c.
Yes you have to include them both. I mostly work in C++ and I try to include files in my .cpp files whenever possible and in my .h files only if I must. This often means doing some type of forward reference in the .h file.
Some platforms I've worked on create a .h that includes a bunch of standard files so that the you can just include the one file. Personally, I've never particularly liked this approach.
Every .h file you write should have what are known as "include guards". These are #ifdef statements that prevent a header from getting included more than once. You;ll notice the ones you mentioned already have include guards in place. But make sure you put them in your foo.h and bar.h too.
You will have to include the header in any file which is compiled by itself even if you will be linking it later.
There is already an #ifdef in the header so that it will only be actually used once.