Reputation: 640
I am currently experiencing a problem that I can solve easily, but I know there is another way to solve it so I am asking you help to figure it out :)
It's a classical problem: I have a 2 struct that need each others. To be more specific, here is the code:
a.h
#ifndef __A__
#define __A__
#include "b.h"
typedef struct {
... // there is no B
} A;
void A_func(A, B);
#endif
b.h
#ifndef __B__
#define __B__
#include "a.h"
typedef struct {
... //there is no A
} B;
void func_B(B, A);
#endif B
In my case, gcc is shouting me unknown type A
in b.c
I can manage that using another file containing the functions that use A
and B
, but I do not really want to...
Do you know a way to solve this?
Upvotes: 2
Views: 2481
Reputation: 145287
You should use struct
tags instead of just defining unnamed struct typedefs.
Here is a simple fix for your case:
a.h
#ifndef __A__
#define __A__
struct B; // forward declaration
typedef struct A {
... // there is no B
} A;
void A_func(struct A, struct B);
#endif /* __A__ */
b.h
#ifndef __B__
#define __B__
struct A; // forward declaration
typedef struct B {
... //there is no A
} B;
void func_B(struct B, struct A);
#endif /* __B__ */
Upvotes: 1
Reputation: 170211
There are two steps to resolve this.
1) Avoid the typedef
. They don't provide a useful abstraction here, only syntactic sugar. And it comes at the price of being able to write correct code, as the next point demonstrates.
2) Even for passing structures by value, a function prototype requires no more than a forward declaration. The full structure definition is required only at the function definition, and calling code site.
With that in mind:
//a.h
#ifndef __A__
#define __A__
struct A{
... // there is no B
};
struct B; // Forward declaration
void A_func(struct A, struct B);
#endif
//b.h
#ifndef __B__
#define __B__
struct B{
... //there is no A
};
struct A; // Forward declaration
void func_B(struct B, struct A);
#endif
So yes, you must type struct A
to refer to the type, but it conveys a lot of information! A reader of your code will know it's a structure type, possibly very large. They will be more likely to use your API properly if that information isn't hidden away from them.
But note the beautiful thing: neither header requires the other anymore. The mutual dependency between them has been reduced to just knowing about the names in each other. A user of a.h
need never include b.h
if they don't use A_func
.
Upvotes: 3