It's not necessarily redundant. The fact that you have separate header files and source files means that you can swap src and header files around as long as the source files provide definitions for the header files.
The .h file should include only things that are used in the header. It doesn't need stdio for example if there are no io declarations in the header, instead it should only go in the src file if it is using printf for example.
But there might be situations where one header you can use will need a particular include, while another header won't (e.g. when one header is a more restrictive interface than the other), in which case it's better to duplicate the .h includes.
Since it's guarded, it really makes no difference to the final object/exe you produce, and it doesn't increase compile time by anything worth worrying about, so it's better to include them just in case you want to use a different .h file at some point.
edit: more concrete example
inc1.h
#ifndef INC1_H
#define INC1_H
inc1_struct {
int x;
};
#endif
inc2.h
#ifndef INC2_H
#define INC2_H
#include "inc1.h"
void inc2_f();
struct inc1_struct *inc2_callinc1();
#endif
prog.cpp
#include "inc1.h"
#include "inc2.h"
#include
#include
void inc2_f() {
printf("inc2_f\n");
}
struct inc1_struct *inc2_callinc1() {
return (struct inc1_struct*) malloc(sizeof(struct inc1_struct));
}
int main(int argc, char **argv) {
struct inc1_struct *s = inc2_callinc1();
return 0;
}
This would compile, but lets say you don't want to expose
struct inc1_struct *inc2_callinc1();
in inc2.h
Then you won't need to include inc1.h in the inc2.h file, but if you don't want to also delete the definition of inc2_callinc1() in prog.cpp, then you need to have included inc1.h.