so I know that you cannot use #include
into headers file.
You are mistaken. You can, and often should and want to, use several include directives in your header file.
A typical small C project (e.g. less than a hundred thousands lines of C code in total) often would have a single common header file, e.g. myheader.h
, typically starting with an include guard and several system includes, so like
#ifndef MYHEADER_INCLUDED
#define MYHEADER_INCLUDED
// some system includes
#include <stdio.h>
#include <stdlib.h>
/// your type declarations
enum foo_en { /* blablabla */ };
struct bar_st { /* blablabla */ };
typedef struct bar_st Bar;
/* etc... */
/// your global functions
extern int myglobfun(int, int);
/* etc...*/
/// your global variables (have only a few of them)
extern Bar*my_bar;
/* etc... */
#endif /*MYHEADER_INCLUDED*/
This is just one possibility of organizing a project. Some people prefer to have many header files and explicitly #include
system headers before some of their own headers in every of their translation units (e.g. C source files).
The advantage of having a single common header is that the Makefile
is simple to code, and you might even precompile your common header. A disadvantage is that any change (e.g. adding a field in a common struct
) in that header forces make
to recompile everything (not a big deal for a small project).
Alternatively you could have many header files, then be sure to use include guards (in the single common header case it is actually useless but does not harm) in them, and to define a discipline regarding multiple inclusion. Often, a header file would itself include other needed header files, or else check that they have been included, e.g. with
// file "myheaderone.h"
#ifndef MYHEADERONE_INCLUDED
// check that "myotherheader.h" has been included
#ifndef MYOTHERHEADER_INCLUDED
#error myotherheader.h should have been #include-d
#endif
//// etc
Alternatively you might code #include "myotherheader.h"
near the beginning of myfirstheader.h
If you have multiple headers, you need a complex Makefile
and you'll rather generate the dependencies, see this. It uses some preprocessor options to gcc
like -M
and friends.
BTW, your Makefile
is wrong. Don't hardcode cc
in it (but use $(CC)
). Be sure to ask GCC for all warnings & debug info (e.g. CFLAGS= -Wall -g
). Learn about GNU make catalog of rules by running make -p
. And your CFLAGS= -I
is really wrong, you might want CFLAGS= -I. -Wall -g
since -I
should always be followed by a directory.
PS. If using gcc
take the habit of always passing -Wall
to it. Very often (and certainly in your case) you also want -Wextra
(to get even more warnings; remember the compiler warnings are your friends and you should improve your code till you have none of them) and probably -g
(to be able to use the -g
debugger). For benchmarking purposes ask the compiler to optimize (e.g. with -O1
or -O2 -mcpu=native
).
Be aware of the -H
preprocessor option: it is asking gcc
to show every included file. Sometimes (e.g. to debug some nasty macro) you want to see the preprocessed form of a translation unit, use gcc -C -E
to get it.