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?
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.
ISO/IEC 9899:2011
7.1.3 Reserved identifiers
¶1 Each header declares or defines all identifiers listed in its associated subclause, and
optionally declares or defines identifiers listed in its associated future library directions
subclause and identifiers which are always reserved either for any use or for use as file
scope identifiers.
— All identifiers that begin with an underscore and either an uppercase letter or another
underscore are always reserved for any use.
— All identifiers that begin with an underscore are always reserved for use as identifiers
with file scope in both the ordinary and tag name spaces.
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:
main.c
main.h
child1.c
child1.h
child2.c
child2.h
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 in child1.c
or the code in child1.c
uses the material from main.c
(or possibly both). Therefore, either main.c
should include child1.h
or child1.c
should include main.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 uses size_t
, for example, you need to #include <stddef.h>
in c8b10.h
.
In your circumstances, I'd expect that your C8B10
structure should be defined in main.h
and both child1.c
and child2.c
should include main.h
. It is likely that main.c
should also include both child1.h
and child2.h
. And main.h
should include the external c8b10.h
header, so in fact every file includes that.
main.c
main.h
c8b10.h
child1.h
child2.h
child1.c
main.h
c8b10.h
child1.h
child2.c
main.h
c8b10.h
child2.h
Whether child2.c
needs to include child1.h
and whether child1.c
needs to include child2.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 header c8b10-private.h
. The c8b10-private.h
header would be included by each source file in the library. The first header it would include is the external c8b10.h
header (to help automatically check that the c8b10.h
header is self-contained). The c8b10-private.h
header would correspond to the merger of main.h
, child1.h
and child2.h
, minus the externally accessible content defined in c8b10.h
. This leads to:
main.c
c8b10-private.h
c8b10.h
child1.c
c8b10-private.h
c8b10.h
child2.c
c8b10-private.h
c8b10.h
The key point to remember is that headers are for communicating between source files. The rest follows largely automatically from that.
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.