I've got two header files, each requiring a type defined in the other. When I try to compile, I get an error regarding an unknown type name. (If I provide only struct declarations and not definitions, I get an incomplete-types error.) What's a solution that will let me share these structs properly?
Right now, my code looks rather like the following (just imagine the #ifndef preprocessor directives etc.):
<headerA.h>
#include "headerB.h"
typedef struct {
mytypeB myB;
} mytypeA;
<headerB.h>
#include "headerA.h"
typedef struct {} mytypeB;
void foo( mytypeA * myA);
You should forward-declare the struct mytypeA instead of including headerA.h:
Inside headerB.h:
struct mytypeA; // <<<--- Forward declaration
void foo(struct mytypeA* myA);
This works because you are not using the actual mytypeA, only a pointer to it. You cannot pull the same trick with headerA, because mytypeA includes the actual mytypeB.
You can forward declare a structure without needing to define the whole thing.
These SO questions might help you since it is related to your question.
undefined C struct forward declaration
How to declare a structure in a header that is to be used by multiple files in c?
Related
I am pretty new to C and have the following issue with a framework specific datatype that is used within an extern declared function for a parameter inside a header file.
//FILE: example.h
extern void my_function(void *);
//FILE: example.c
#include "example.h"
#include "freertos/task.h"
void my_function(TaskHandle_t _taskHandle){
//function body
}
The datatype TaskHandle_t is of course not known in the header as I would have to include the freertos header here as well. I heard including other header files inside a header file is bad practise.
If I try to compile the example above the following error raises:
error: conflicting types for 'my_function'
void my_function(TaskHandle_t _taskHandle)
Whats the best approach to solve this problem?
Very much in contrast to the best practice you mention, I follow what I consider a rule:
"Include what you need. Do not include what you do not need."
I am very much with M. Oehm:
If a header file requires definitions from other header files, it should include that header. It sure isn't any worse practice than trying to work around it by using void *.
The concept of forward declaring structs allows to use pointer-to-that before including or typedefining the struct in detail. (As mentioned in the comment be some programmer dude.)
Declaring an otherwise unknown datatype is about the only good reason why you should include a header in a header. However there is also the so-called 'forward declaration', which you can use when you need to pass a pointer to a struct. (Or class in C++)
A forward declaration simply looks like this:
//.h file
struct YourType;
void yourFunction(struct YourType *variable);
//.c file
#include "HeaderContainingYourType.h"
void yourFunction(struct YourType *variable)
{
}
As for your specific problem, your prototype and your declaration must have the exact same signature, so if you declare the prototype with void *, you must use void * in the declaration too.
Ways to solve your problem:
Include the header file you need.
Pull out the typedef from the header file and redeclare it verbatim in your new header file.
Pass void * and cast it to the appropriate type in the C file.
Please note, that the third approach negates the aspect of 'typesafety', since you can pass anything to a void *.
If TaskHandle_t is a pointer to struct then you can forward declare the struct and add an alias for a pointer to it.
typedef struct TaskHandle_s *TaskHandle_t;
void my_function(TaskHandle_t _taskHandle);
I've a slight problem with my include files and I've made a simplified mockup of my problem.
Say I'm compiling some source that requires a header file named
header.h
Which has in it:
#ifndef HEADER_INCLUDED
#define HEADER_INCLUDED
#include element.h
typedef struct {
Element *list;
} Thing;
#endif
Then I have another header file defining that Element and also requiring header.h.
element.h
#ifndef ELEMENT_INCLUDED
#define ELEMENT_INCLUDED
typedef struct Element;
#include header.h
void * func(Thing *myThing);
#endif
I then run into a problem because element.h can't know what the Thing type is; we haven't reached that definition in header.h because we needed to include element.h.
I thought I could maybe solve my problem for "forward typedefing" a Thing type in element.h and right before the void * func prototype like
typedef struct thing Thing;
Then this just creates another problem and the compiler complains that there are conflicting types for Thing.
How do I get out of this mess?
Your main problem is that there is a cyclic dependency between the 2, yet you're using guard macros. The files are included almost as if by copy-paste - one of the files has to be included before the other, so you cannot have such cyclic dependency. Rethink your structure.
Declare/define the basic data type in 1 place, then the derived/composite data types using that, and finally the functions that take those types as arguments/return values.
Also, typedef struct Element; is invalid typedef.
Simplest way to solve your problem is to isolate your struct definition in its own header, protected by #ifndef/#define as usual. If you don't want a header file for this single struct, define the struct twice and protect its definition by another #ifndef/#define this way:
#ifndef __BOOLEAN_ENUM__
#define __BOOLEAN_ENUM__
enum boolean
{
false = 0,
true = 1
};
#endif
header.h should not include element.h. Otherwise you have circular dependency.
The code you posted has a large number of errors. (In future, post real code that you tried to compile, instead of making stuff up as you go in the edit box). Here is an example, where I have omitted the header guards for brevity:
// header.h
struct Element; // actually not necessary, but may help with readability
typedef struct
{
struct Element *ptr;
} Thing;
and
// element.h
#include "header.h"
struct Element
{
int x;
};
typedef struct Element Element; // optional
void * func(Thing *myThing);
It would be possible to also place typedef struct Element Element; in header.h and use Element *ptr inside the definition of Thing, it is a matter of taste as to which way you prefer. Some people disapprove of using typedef with structs at all in C, however I like it as it means that a typo leads to an immediate compilation error, instead of silently creating a new type.
If you also want element.h to not depend on header.h, you can use the same technique with Thing. You need to give it a struct tag , like how struct Element has.
Just step back from the C code and thing of the overall program design.
It is clear that the "Thing" struct must depend on the "Element" struct in element.h. However, it doesn't make any sense to use functions that depend on "Thing" from inside the element header. It rather makes most sense that functions using "Thing" should be inside the "Thing" header.
If you look at it with an object-oriented approach, which you should no matter programming language, then Element is a class, Thing is a class. The function could either be a member function of Thing, or it could be a non-related function using that class.
What you would do in object-oriented C, is to declare both "Element" and "Thing" as incomplete types in their respective headers. The type definition is hidden from the caller, and only present in those header's respective C files, called element.c and thing.c. All member functions dealing with the respective classes will be declared in the headers and defined in the C files. (This design is also sometimes called opaque type or opaque pointers.)
Functions using either class will then simply include the needed header.
In C often structs are typedefed to avoid writing struct everywhere.
When using this names as opaque pointer parameters in headers you have to forward declare them. It is rather annoying that the whole typedef has to be duplicated.
Example:
some header defines some types:
typedef struct sBlaBlaFooBar{
int someData;
}BlaBlaFooBar;
Some other header uses this structure as pointer parameter. But to avoid huge include dependencies BlaBlaFooBar.h should not be included and just a forward declaration is used.
So you have to write typedef struct sBlaBlaFooBar BlaBlaFooBar; to forward declare it.
That does bother me is the redundancy that i have to know the tag name of the structure because normally it does not matter. And if it is changed, all the forward declarations also have to be changed even if the typename is the same.
Is there some smart way around this?
more detailed explanation:
a lot of headers with structure definitions (that may be also composed structures (just to show deep dependency graphs))
s1.h
s2.h
s3.h
s4.h
a BlaBlaFooBar header with a BlaBlaFooBar structure that is a composite of all these.
Additional structures BlaBlaBarFoo with similar topology (from other sub structures)
then modules that defines new structures NewStruct and functions NewStruct_create(NewStruct* out, const BlaBlaFooBar* in); that processes
the above structures as input. These headers only need the typedefs and only the implementation has to know about exact BlaBlaFooBar structure definitions.
Addional modules that only work on NewStruct and to not necessarily have to be recompiled if BlaBlaFooBar changes.
So to avoid these kind of dependencies the structures have to be forward declared in the header and the c-file includes the definition.
Use 2 include files:
blabla.h
#include "light_dependencies.h"
typedef struct sBlaBlaFooBar BlaBlaFooBar;
blabla_internal.h
#include "blabla.h"
#include "heavy_dependencies.h"
struct sBlaBlaFooBar {
...
};
blabla.c
#include "blabla_internal.h"
/* Here is code which deals with the internals of the struct */
usercode.c
#include "blabla.h"
/* Here is code which only passes struct pointers around */
I am just getting back into the C programming realm and I am having an issue that I think is linker related.
I am using cmake for the first time as well, so that could be adding to my frustration.
I have included a third party header file that contains a typedef that my code is trying to use, and it has this line:
typedef struct pcap pcap_t;
so my code has
pcap_t *var;
//later.....
var->fd;// this line throws the error
which throws the
error: dereferencing pointer to incomplete type
So am I just missing another include file, or is this a linker issue? I am building this code in QtCreator and using cmake. I can dive on a_t to see that typedef declaration in the included header, but I can't seem to dive on "struct a" itself to see where it's coming from.
Thanks
edited the code above to reflect that I am using the pcap libraries
so i have included in my source file's header file the following lines
#include <net/bpf.h>
#include <pcap/pcap.h>
so I guess between these two includes, I am missing the defintion of the pcap structure. Where can I find it?
Thanks
The typedef statement does two things. It declares the existence of something of type struct a. It also declares that a_t is an alias for struct a. Declaring the existence of a type without any information to determine its size is called by the C language an incomplete type. The declaration is colloquially referred to as a forward declaration, and the type is colloquially referred to as opaque to those parts of the code that never get to see the type's definition.
typedef struct a a_t;
a_t *var;
The C language allows pointers to an incomplete type to be defined. A pointer to an incomplete type is not itself incomplete, since a pointer to a type is the same size as a void pointer. But, your code then attempts to dereference the pointer:
var->member;
Since there is no definition of struct a available, the compiler has caught an error in your program, and is telling you about it. It is not a linker issue, but a semantic error in your program.
An opaque type is a way to hide implementation details from the user of the type. That is, it is C's way of providing an interface:
typedef struct a a_t;
a_t *a_create ();
void a_destroy (a_t *);
int a_get_member (a_t *);
void a_set_member(a_t *, int);
Then, in your code, you are expected to use the interface.
a_t *var = a_create();
a_set_member(var, 10);
int m = a_get_member(var);
a_destroy(var);
The source file that implements the interface would actually define what struct a looks like. Since you said you had no definition to reference in your debugger, this likely means you did not provide a definition anywhere in your program.
Edit: It seems you are trying to use the packet capture library. You will need to include the <pcap.h> header file to your code, and link with -lpcap. If the header file or library does not exist, you will need to install the packet capture development package for your OS. The <pcap.h> has made a typedef for pcap_t already, and it is intentionally opaque. So you will have to use the interfaces the header file defines to access the information you want.
I'm trying to translate the important parts of OpenMPI's mpi.h to the D programming language so I can call it from D. (HTOD didn't work at all.) I can't wrap my head around the following bits of code:
typedef struct ompi_communicator_t *MPI_Comm;
OMPI_DECLSPEC extern struct ompi_communicator_t ompi_mpi_comm_world;
OMPI_DECLSPEC extern struct ompi_communicator_t ompi_mpi_comm_self;
OMPI_DECLSPEC extern struct ompi_communicator_t ompi_mpi_comm_null;
The problem is that ompi_communicator_t is never defined in mpi.h and mpi.h doesn't include any other file besides stddef.h, which clearly doesn't contain a definition. (The comment says it's included for ptrdiff_t.) These are the only four lines in mpi.h that contain the string ompi_communicator_t. Where is the definition of this struct coming from? Are there any tricks I should be aware of where types can appear out of thin air? (There are several other structs like this, but this is the first one I stumbled upon.)
This is a pointer to the struct, which internals are not visible outside the OpenMPI. Use any type which can hold a pointer, e.g. (in C) void*.