Reputation: 859
Does anybody have any tip how to handle the symbolic constants and types definition in large program in a system manner to avoid circular dependencies between the header files? I have an idea to define one header file which will contain all structs, unions and enum types definitions and another header file which will contain all symbolic constants definitions. But I have doubts as far as this solution regarding to implementation hiding. Thank you for any ideas.
Upvotes: 8
Views: 11021
Reputation: 214730
The solution is to simply use some manner of program design. Each "object"/"module" in your program should consist of one h file and one c file. The h file is the public interface. Each such object should only be concerned with its own designated task. It should only include the resources needed to perform that task.
With such a design, there should never be any circular dependencies, or the design is flawed. You should not fix a bad design with various code tricks, you should re-do the design.
But of course the same resource could be included multiple time from different parts of the code. This is why we always use header guards in every single h file.
Upvotes: 4
Reputation: 8142
You can separate out the typedef
statements from the actual struct
definitions and place them before including the other headers. This way if your datatype foo
contains a member of type bar *
, it doesn't need the definition of bar
straight away - it'll be happy enough knowing that it's a valid datatype that will get resolved later.
#ifndef FOO_H
#define FOO_H
typedef struct foo_s foo;
#include "bar.h"
struct foo_s
{
bar *my_bar;
};
#endif
.
#ifndef BAR_H
#define BAR_H
typedef struct bar_s bar;
#include "foo.h"
struct bar_s
{
foo *my_foo;
};
#endif
Upvotes: 9
Reputation: 999
In any given header file, put
#ifndef FILENAME_H
#define FILENAME_H
struct a {}
union b {}
function c();
#endif
This will cause the file to be included only once.
Upvotes: -1