Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C header file loops

I have a couple of header files, which boil down to:

tree.h:

#include "element.h"

typedef struct tree_
{
    struct *tree_ first_child;
    struct *tree_ next_sibling;
    int tag;
    element *obj;
    ....
} tree;

and element.h:

#include "tree.h"

typedef struct element_
{
    tree *tree_parent;
    char *name;
    ...
} element;

The problem is that they both reference each other, so tree needs element to be included, and element needs tree to be included.

This doesn't work because to define the 'tree' structure, the element structure must be already known, but to define the element structure, the tree structure must be known.

How to resolve these types of loops (I think this may have something to do with 'forward declaration'?)?

like image 319
Scooby Avatar asked Sep 28 '08 20:09

Scooby


People also ask

What should be in a C header file?

The header file contains only declarations, and is included by the . c file for the module. Put only structure type declarations, function prototypes, and global variable extern declarations, in the . h file; put the function definitions and global variable definitions and initializations in the .

How many C header files are there?

There are 19 header files in the Standard C Library. All files have the . h file extension.


1 Answers

Crucial observation here is that the element doesn't need to know the structure of tree, since it only holds a pointer to it. The same for the tree. All each needs to know is that there exists a type with the relevant name, not what's in it.

So in tree.h, instead of:

#include "element.h"

do:

typedef struct element_ element;

This "declares" the types "element" and "struct element_" (says they exist), but doesn't "define" them (say what they are). All you need to store a pointer-to-blah is that blah is declared, not that it is defined. Only if you want to deference it (for example to read the members) do you need the definition. Code in your ".c" file needs to do that, but in this case your headers don't.

Some people create a single header file which forward-declares all the types in a cluster of headers, and then each header includes that, instead of working out which types it really needs. That's neither essential nor completely stupid.

The answers about include guards are wrong - they're a good idea in general, and you should read about them and get yourself some, but they don't solve your problem in particular.

like image 70
Steve Jessop Avatar answered Sep 16 '22 15:09

Steve Jessop