Как уже отмечали другие, заголовок foo.h должен объявлять информацию, необходимую для возможности использования средств, предоставляемых исходным файлом foo.c. Это будет включать типы, перечисления и функции, предоставляемые foo.c. (Вы не используете глобальные переменные, не так ли? Если вы используете, то они также объявлены в foo.h.)
Заголовок foo.h должен быть автономным и идемпотентным. Автономный означает, что любой пользователь может включить foo.h и ему не нужно беспокоиться о том, какие другие заголовки могут понадобиться (потому что foo.h включает эти заголовки). Идемпотент означает, что если заголовок включен более одного раза, то никакого ущерба не будет. Это достигается классической техникой:
#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED
...rest of the contents of foo.h...
#endif /* FOO_H_INCLUDED */
Заданный вопрос:
Файл foo.c включает в себя foo.h, который содержит все объявления для foo.c; То же самое для bar.c и bar.h. Функция foo1 () внутри foo.c вызывает bar1 (), которая объявлена в bar.h и определена в bar.c. Теперь вопрос в том, должен ли я включить bar.h внутри foo.h или внутри foo.c?
Это будет зависеть от того, зависят ли сервисы, предоставляемые foo.h, от bar.h или нет. Если другим файлам, использующим foo.h, понадобится один из типов или перечислений, определенных bar.h, чтобы использовать функциональность foo.h, то foo.h должен убедиться, что bar.h включен (включив его). Однако, если сервисы bar.h используются только в foo.c и не нужны тем, кто использует foo.h, тогда foo.h не должен включать bar.h