I want to have a struct that contains a pointer to another struct which in turn has a function pointer with the function argument being a pointer to the first type of struct but I'm struggling to resolve the references. The struct definitions are in different header files and must be available to other code in the full project.
In a simplified example, in main I have:
#include "a.h"
typedef struct {
int x;
int (*func)(a_t * a);
int y;
} z_t;
In a.h:
#ifndef A_H_
#define A_H_
#include "z.h"
typedef struct {
int b;
int c;
z_t * z;
} a_t;
#endif /* A_H_ */
and in z.h:
#ifndef Z_H_
#define Z_H_
#include "a.h"
typedef struct {
int x;
int (*func)(a_t * a);
int y;
} z_t;
#endif /* Z_H_ */
I end up with circular #includes and type a_t is unknown in z.h
Can anyone help?
In C, you can have a circular reference among two or more structures, or from a structure to itself. Note that the reference can be by pointer only: one structure X cannot embed an instance of another while simultaneously X embeds an instance of Y. However, X can have a pointer to Y, while Y can point to X, or embed a copy of X.
The mechanism which allows a circular reference in C is the incomplete struct type. In C you can use struct in a declaration, without defining the body of the struct, like this:
struct foo *bar; // foo has never been seen before.
The foo identifier is the "struct tag". A later re-declaration of the same struct tag in the same scope which does include a body will complete the type:
struct foo { int member; }; // foo is now complete
With this we can do:
struct list_node {
struct list_node *next, *previous; // self reference
};
struct foo {
struct bar *bar_ptr;
};
struct bar {
struct foo *foo_ptr; // mutual references
};
In your code, you haven't used a single struct tag; all your struct types are anonymous, and you are relying on typedef aliases. The above referential tricks cannot be played out using typedef names; the struct tags are essential.
Only a struct which has a tag can be declared two or more times: incomplete the first times, and then completely. The declaration of a struct with no tag is anonymous; such a declaration invents a new, unique struct type each time it appears.
Related
#ifndef STAGE_TABLE_DEFINITION_HEADER
#define STAGE_TABLE_DEFINITION_HEADER
typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
typedef struct {
uint32_t error_number;
stage_t* current_stage;
} stage_table_context_t;
#endif
Getting an unknown type error on stage_table_context_t.
The function pointer stage_table_function_t refers to stage_table_context_t and stage_table_context_t refers to stage_table_function_t.
Obviously positioning doesn't matter here since either orientation will result in an issue. Seems I need to forward declare the stage table context structure, but not sure how to do this with a typedef.
Apologies for the stupid question, I've been away from C for 6 months and I'm having a bit of a brain fart.
edit: Fixed some typo's in the code.
You can make the declaration of a struct before its definition:
/* declaration */
struct foo;
.....
/* definition */
struct foo
{
....
};
Anywhere you write struct foo is a declaration of the struct, so you don't have to put it in a separate line, you can have it in a typedef, pointer declaration, etc..
Just be aware that sometimes, like in variable declarations of type struct foo you also need the definition (to calculate the variable size);
/* declare struct foo ..*/
struct foo;
/* .. or declare struct foo ..*/
typedef struct foo foo;
/* .. or declare struct foo ..*/
struct foo *p;
/* .. or declare struct foo */
int bar (struct foo *p);
/* Not valid since we don't have definition yet */
struct foo f1;
/* definition */
struct foo
{
....
};
/* Valid */
struct foo f2;
In your case you haven't given the struct a name; you've just made a typedef that is an alias for an anonymous struct. So to forward declare your struct you have to give it a name:
/*
forward declare the `struct stage_table_context_t` and give it a typedef alias
with the same name as the structs name
*/
typedef struct stage_table_context_t stage_table_context_t;
typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
struct stage_table_context_t{
uint32_t error_number;
stage_t* current_stage;
} stage_table_context_t;
You just have to tell the compiler that stage_table_context_t shall be a struct; by that, you implicitly forward-declare the struct stage_table_context_t, which's actual definition may then come later. Note that a typedef does not define a struct, it just introduces an alias. So the actual definition is struct stage_table_context_t { ..., regardless of whether you introduce an alias for it or not (and regardless of which name you use for the alias).
typedef struct stage_table_context_t* (*stage_table_function_t)(struct stage_table_context_t*);
typedef struct {
const char* stage_name;
stage_table_function_t* function;
} stage_t;
struct stage_table_context_t {
uint32_t error_number;
stage_t* current_stage;
};
// optional (if you want to use "stage_table_context_t" as an alias for "struct stage_table_context_t"):
typedef struct stage_table_context_t stage_table_context_t;
I wrote a small code in C in which two struct types were defined which have members of each other in their definition. Case 1: If the struct foo is defined before struct bar, the code is compiled as expected. Case 2: If struct foo is defined after struct bar it will not compile which is also expected as there is no way to know the memory requirement of a struct foo variable. But I was expecting it will compile if a forward declaration of struct foo is used in case 2. But it does not work. What am I missing?
#include<stdio.h>
#include<stdlib.h>
struct foo; // forward declaration
struct bar
{
int a;
struct bar *next;
struct foo ch;
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
forward declaration only informs the compiler that there is something that is called foo it does nothing says about size.
you can use foo* since this is a pointer of known size but not foo itself because the size is unknwon, so the compiler does not know how the memory layout of barshould look like.
And the compiler only do a single pass through your document. so it cannot know the strucutre that is defined ahead.
If a struct type X appears only as a pointer type in a structure declaration or its functions, and the code in the header file does not attempt to access any member variables of X, then you should not #include X.h, but instead make an incomplete declaration of X (also called a
"forward" declaration) before the first use of X. Here is an example in which a structure type Thing refers to X by a pointer:
struct X; /* incomplete ("forward") declaration */
struct Thing {
int i;
struct X* x_ptr;
};
The compiler will be happy to accept code containing pointers to an incompletely known structure type, basically because pointers always have the same size and characteristics regardless of what they are pointing to. Typically, only the code in the .c file needs to access the members (or size) of X, so the .c file will #include "X.h". This is a powerful technique for encapsulating a module and decoupling it from other modules.
That is, it would work correctly if your code was something like :
#include<stdio.h>
#include<stdlib.h>
struct foo; // forward declaration
struct bar
{
int a;
struct bar *next;
struct foo *ch; /* MODIFIED LINE */
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
But in your case, struct bar is having an "element" of type struct foo. Hence it will give error field has incomplete type.
Also for your information, see the below snippet (will work perfectly):
#include<stdio.h>
#include<stdlib.h>
struct bar
{
int a;
struct aabar *next; /* MODIFIED LINE - aabar never declared */
struct foo *ch;
};
struct foo
{
struct bar *n;
struct foo *nx;
};
int main()
{
struct bar p;
return(0);
}
A declaration also can't let the compiler know how to allocate the memory.
In your struct foo the element nx is a pointer, so defining struct foo doesn't require memery size. However, on struct bar the element ch is not a pointer, so the defining struct bar needs to know the size of struct foo. The forward declaration doesn't specify the memory size, the definition does.
I am using Kdevelop in Kubuntu.
I have declared a structure in my datasetup.h file:
#ifndef A_H
#define A_H
struct georeg_val {
int p;
double h;
double hfov;
double vfov;
};
#endif
Now when I use it in my main.c file
int main()
{
georeg_val gval;
read_data(gval); //this is in a .cpp file
}
I get the following error:
georeg_chain.c:7:3: error: unknown type name 'georeg_val'
(This is in the georeg_val gval; line)
I would appreciate if anyone could help me resolve this error.
In C one has two possibilities to declare structure:
struct STRUCT_NAME {} ;
or
typedef struct {} STRUCT_ALIAS;
If you use first method (give struct a name) - you must define variable by marking it explicitly being a struct:
struct STRUCT_NAME myStruct;
However if you use second method (give struct an alias) then you can omit struct identifier - compiler can deduce type of variable given only it's alias :
STRUCT_ALIAS myStruct;
Bonus points:
You can declare struct with both it's name and alias:
typedef struct STRUCT_TAG {} STRUCT_TAG;
// here STRUCT_NAME == STRUCT_ALIAS
Then in variable definition you can use either first or second method. Why both of two worlds is good ? Struct alias lets you to make struct variable definitions shorter - which is a good thing sometimes. But struct name let's you to make forward declarations. Which is indispensable tool in some cases - consider you have circular references between structs:
struct A {
struct B * b;
}
struct B {
struct A * a;
}
Besides that this architecture may be flawed - this circular definition will compile when structs are declared in the first way (with names) AND struct pointers are referenced explicitly by marking them as struct.
If you have to define a new type, you have to write:
typedef struct {
int p;
double h;
double hfov;
double vfov;
} georeg_val ;
Then you can use georeg_val as a new type.
Defining a struct type (on this example, a binary search tree struct):
struct tree {
int info;
struct tree *left;
struct tree *right;
}
typedef struct tree treeNode;
Declaring a function eg.:
treeNode *insertElement(treeNode *treeA, int number);
I want use a typedef struct that isn't already defined, but it is later.
Is there anything like a struct prototype?
file container.h
// i would place a sort of struct prototype here
typedef struct
{
TheType * the_type;
} Container;
file thetype.h
typedef struct {......} TheType;
file main.c
#include "container.h"
#include "thetype.h"
...
Replace this line:
// i would place a sort of struct prototype here
with these lines:
struct TheType;
typedef struct TheType TheType;
Since you need the type TheType to be defined before type Container is defined, you have to use forward declaration of type TheType - and to do so you also need forward declaration of struct TheType.
Then you will not define typedef TheType like this:
typedef struct {......} TheType;
but you will define struct TheType:
struct {......};
In container.h:
struct _TheType;
typedef struct _TheType TheType;
Than in thetype.h:
struct _TheType { ..... };
You can declare a struct inside the typedef:
typedef struct TheType_Struct TheType; // declares "struct TheType_Struct"
// and makes typedef
typedef struct
{
TheType * p;
} UsefulType;
Note though that you may only have at most one typedef in one translation unit in C89 and C99 (this differs from C11 and C++).
Later on you must define the actual struct TheType_Struct { /* ... */ }.
You cannot define an object of an, as yet, undefined struct; but you can define a pointer to such a struct
struct one {
struct undefined *ok;
// struct undefined obj; /* error */
};
int foo(void) {
volatile struct one obj;
obj.ok = 0; /* NULL, but <stddef.h> not included, so 0 */
if (obj.ok) return 1;
return 0;
}
The above module is legal (and compiles with gcc without warnings).
I've seen C structs declared several different ways before. Why is that and what, if anything, does each do different?
For example:
struct foo {
short a;
int b;
float c;
};
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
int main (int argc, char const *argv[])
{
struct foo a;
bar b;
baz c;
return 0;
}
Well, the obvious difference is demonstrated in your main:
struct foo a;
bar b;
baz c;
The first declaration is of an un-typedefed struct and needs the struct keyword to use. The second is of a typedefed anonymous struct, and so we use the typedef name. The third combines both the first and the second: your example uses baz (which is conveniently short) but could just as easily use struct _baz to the same effect.
Update: larsmans' answer mentions a more common case where you have to use at least struct x { } to make a linked list. The second case wouldn't be possible here (unless you abandon sanity and use a void * instead) because the struct is anonymous, and the typedef doesn't happen until the struct is defined, giving you no way to make a (type-safe) pointer to the struct type itself. The first version works fine for this use, but the third is generally preferred in my experience. Give him some rep for that.
A more subtle difference is in namespace placement. In C, struct tags are placed in a separate namespace from other names, but typedef names aren't. So the following is legal:
struct test {
// contents
};
struct test *test() {
// contents
}
But the following is not, because it would be ambiguous what the name test is:
typedef struct {
// contents
} test;
test *test() {
// contents
}
typedef makes the name shorter (always a plus), but it puts it in the same namespace as your variables and functions. Usually this isn't an issue, but it is a subtle difference beyond the simple shortening.
It's largely a matter of personal preference. I like to give new types a name starting with a capital letter and omit the struct, so I usually write typedef struct { ... } Foo. That means I cannot then write struct Foo.
The exception is when a struct contains a pointer to its own type, e.g.
typedef struct Node {
// ...
struct Node *next;
} Node;
In this case you need to also declare the struct Node type, since the typedef is not in scope within the struct definition. Note that both names may be the same (I'm not sure where the underscore convention originated, but I guess older C compilers couldn't handle typedef struct X X;).
All your uses are syntactically correct. I prefer the following usage
/* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
short a;
int b;
foo* next;
};
Observe that this easily allows to use the typedef already inside the declaration of the struct itself, and that even for struct that reference each other mutually.
The confusion comes about because some of the declarations are in fact declaring up to three C constructs. You need to keep in mind the difference between:
A typedef declaration,
A struct definition, and
A struct declaration.
They are all very different C constructs. They all do different things; but you can combine them into the one compound construct, if you want to.
Let's look at each declaration in turn.
struct foo {
short a;
int b;
float c;
};
Here we are using the most basic struct definition syntax. We are defining a C type and give it the name foo in the tag namespace. It can later be used to declare variables of that type using the following syntax:
struct foo myFoo; // Declare a struct variable of type foo.
This next declaration gives the type another name (alias) in the global namespace. Let's break it down into its components using the previous basic declaration.
typedef foo bar; // Declare bar as a variable type, the alias of foo.
bar myBar; // No need for the "struct" keyword
Now just replace "foo" with the the struct's definition and voila!
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
The above syntax is equivalent to the following sequence of declarations.
struct _baz {
short a;
int b;
float c;
}
typedef _baz baz; // Declare baz as an alias for _baz.
baz myBaz; // Is the same as: struct _baz myBaz;