Currently I am writing a library for a communication protocol. For this task I need this struct:
typedef struct _C8B10 {
unsigned int six :6;
unsigned int four :4;
} C8B10;
But where should I define it? I have one 'main' *.h-file that is included by all other libs. The *.c-files for each lib include only the 'parent' *.h-file. The structure is similar to a tree:
Main.h
Main.c
Child.h
Child.c
Child2.h
Child2.c
....
The children always include the Main.h
and the child.c
their parents. But in one library I get the error, that the type is not defined.
At the moment it is declared in the Main.h-file. But where is the best place to put it into?
Header files are usually used like Java's interfaces in the sense that headers define what information is available outside of the implementation.
If the struct should be available outside of the implementation define it in a header, otherwise define it in once in a .c file which is included in the other .c files.
Namespace conflict
Whatever else you do, you should change the structure tag from
_C8B10
to something that does not trample on the namespace reserved to the implementation.Names starting with an underscore are risky; they are there for providers of the system libraries. Obviously, if your library is part of the implementation, this doesn't apply to you, but I think it unlikely that you'd be asking the question if that were the case.
If it was my code, I'd simply drop the underscore:
typedef struct C8B10 { ... } C8B10;
is fine (typedef
names are in the ordinary identifiers namespace, the structure tag is in the tags namespace, and the two do not conflict).Header file organization
Your diagram is backwards from the way most people normally write such diagrams. The source code includes the headers, so it might be diagrammed as:
However, that can't be the whole story. You create a header to share declarations between source files; a header that is included by just one file is not strictly necessary (though there can be legitimate reasons for creating such files). Either the file
main.c
uses some of the functions (and types — and maybe macros or even global variables, perish the thought) defined inchild1.c
or the code inchild1.c
uses the material frommain.c
(or possibly both). Therefore, eithermain.c
should includechild1.h
orchild1.c
should includemain.h
or both.The other aspect that you need to consider with a library is 'how will clients of the library use the code?' This is crucial. What header will the client code need? What functions will the client code need? Will the client code need any type definitions? Will the client code need to access the members of the C8B10 structure, or will they only need to treat it as an opaque type?
Your external header — the one used by clients of the library — should be as small as possible, but self-contained. Let's assume that the external header is
c8b10.h
. If the client source code has#include "c8b10.h"
as the first or only header in the source file, the code in the header should compile. If your interface usessize_t
, for example, you need to#include <stddef.h>
inc8b10.h
.In your circumstances, I'd expect that your
C8B10
structure should be defined inmain.h
and bothchild1.c
andchild2.c
should includemain.h
. It is likely thatmain.c
should also include bothchild1.h
andchild2.h
. Andmain.h
should include the externalc8b10.h
header, so in fact every file includes that.Whether
child2.c
needs to includechild1.h
and whetherchild1.c
needs to includechild2.h
depends on how the code is written and which of the services provided by each file are used where.You might find it more sensible to have just two headers — the external
c8b10.h
header and one internal headerc8b10-private.h
. Thec8b10-private.h
header would be included by each source file in the library. The first header it would include is the externalc8b10.h
header (to help automatically check that thec8b10.h
header is self-contained). Thec8b10-private.h
header would correspond to the merger ofmain.h
,child1.h
andchild2.h
, minus the externally accessible content defined inc8b10.h
. This leads to:The key point to remember is that headers are for communicating between source files. The rest follows largely automatically from that.