This question already has answers here:
forward declaration of a struct in C?
(3 answers)
Closed 22 days ago.
I need the following construct:
// Header file
typedef fc_t (*comdevCbackIsReady_t)(const comdev_t* const module);
typedef struct
{
comdevCbackIsReady_t cbIsReady;
} comdev_t;
This wont compile, because the comdevCbackIsReady_t function pointer type does not know the comdev_t struct type. If I exchange these 2 places, then the struct wont know the func pointer type. My current way around this is declaring the comdevCbackIsReady_t input parameter as void* instead. This is not very clean. Is there a way to somehow "forward declare" one of these?
EDIT this wont compile:
// Header file
struct comdev_t;
typedef fc_t (*comdevCbackIsReady_t)(const comdev_t* const module);
typedef struct
{
comdevCbackIsReady_t cbIsReady;
} comdev_t;
The comdev_t is still an unknown type for the comdevCbackIsReady_t.
In this typedef declaration of a function pointer
typedef fc_t (*comdevCbackIsReady_t)(const comdev_t* const module);
the used name comdev_t is not declared yet. So the compiler issues an error.
You could just introduce the tag name in the structure declaration like
struct comdev_t;
typedef fc_t (*comdevCbackIsReady_t)(const struct comdev_t* const module);
typedef struct comdev_t
{
comdevCbackIsReady_t cbIsReady;
} comdev_t;
Or
typedef struct comdev_t comdev_t;
typedef fc_t (*comdevCbackIsReady_t)(const comdev_t* const module);
struct comdev_t
{
comdevCbackIsReady_t cbIsReady;
};
Related
This question already has answers here:
How to define a typedef struct containing pointers to itself?
(2 answers)
Closed 1 year ago.
How can I make this to work ?
typedef struct {
A_t* obj;
} A_t;
A_t is unknown. But pointer (fixed size). Can I do it without using void* ?
Ok I find
typedef struct A_t A_t;
struct A_t {
A_t* obj;
};
This question already has answers here:
What is 'forward declaration' and the difference between 'typedef struct X' and 'struct X'?
(5 answers)
Closed 3 years ago.
I want to represent a nested ast node
typedef struct ast_assignment
{
char* sym;
ast_node* value;
} ast_assignment;
typedef struct ast_conjunction
{
char* sym;
ast_node* value;
} ast_conjunction;
typedef struct ast_node {
int node_type;
union {
ast_assignment data;
ast_conjunction data;
};
} ast_node;
but no matter what I define first, the compiler tells me that the other struct is an unknown type? How to proceed?
Typedef has to describe an actual type name
Typedefs require a ; after them
Circular type references require a bit of special sauce
Unions require different member names
Might you mean:
struct ast_node; // forward declaration
typedef struct {
char* sym;
struct ast_node* value;
} ast_assignment;
typedef struct ast_conjunction {
char * sym;
struct ast_node* value;
} ast_conjunction;
typedef struct ast_node {
int node_type;
union {
ast_assignment data_asg;
ast_conjunction data_conj;
};
} ast_node;
Expanding on this a bit for a more complete answer.
First, the purpose of a typedef is to install a new name into the compiler that you can use, so typedef struct { ... }; doesn't really do much. It should be typedef struct {...} newtype; so you can use that actual name newtype.
It also requires a semicolon after, which messes me up every time I go back from C# to C :-)
The circular reference thing is tricky, and doing struct mytype; in advance means you can use that name mytype only if it's in a context where knowledge of the structure details don't have to be known. In practice, it means you can use the struct mytype * as a pointer - because this is a fixed size - but this is not allowed:
struct ast_node; // forward declaration
struct some_other_type {
struct ast_node *nodeptr; // this is ok
struct ast_node thisnode; // FAIL
...
};
The reason is: a pointer is a fixed size no matter what kind of data it points to so the compiler carries you a bit, but the thisnode would require knowledge of all the details. Sorry, no way to do that.
Re: the union, you can't define any union or struct with two members with the same name because how could you reference one of them and the compiler would know which?
Personally I'm not a fan of using typedef for structure types, so I'd do this as:
struct ast_node; // forward struct defn
struct asg_assignment {
char *sym;
struct ast_node *value;
};
struct ast_conjunction {
char * sym;
struct ast_node* value;
};
struct ast_node {
int node_type;
union {
struct ast_assignment data_asg;
struct ast_conjunction data_conj;
};
};
... but I'm not sure I can justify this by anything other than personal preference.
You have multiple errors in your code. The correct way to declare a struct is as follows:
struct a {
...
}; // needs a semicolon
And to refer to it, you must use the struct keyword as well;
struct b {
struct a data;
};
In your case, the proper code that will compile is:
struct ast_assignment
{
char* sym;
struct ast_node* value;
};
struct ast_conjunction
{
char* sym;
struct ast_node* value;
};
struct ast_node {
int node_type;
union {
struct ast_assignment data_assignment;
struct ast_conjunction data_conjunction; // you cannot have multiple members with the same name
};
};
In C, the type you want to caƶl has to be declared first.
However, you can just use another pointer like void*.
void* is a pointer that can be used for any type.
If you define type of the later struct in the first struct as void*, the compiler will allow it.
But this has drawbacks. You are losing type safety with this and you may need to cast at some points.
Also, a typedef shortcut does not allow it to be used before the whole the typedef is declared.
This means, you can't use the shortcut inside the struct.
For example, the following would not be possible:
typedef struct mystruct{
myStruct_t *myValue;
} myStruct_t;
You'll need to do this instead:
typedef struct mystruct{
struct myStruct *myValue;
} myStruct_t;
What I want to accomplish: I want to use a typedef'd function pointer inside of a typedef'd struct where the function pointer takes a struct pointer as an argument (i.e. something like an 'object method' which takes a self-reference to the 'object').
I have this C code (simplified, hopefully not oversimplified):
typedef struct MYSTRUCT myStruct;
typedef void (*getSomething)(myStruct*);
typedef struct MYSTRUCT {
getSomething get_something;
};
void get_property() {
myStruct *structure = NULL;
}
So what I think I'm doing is: forward declare the struct, use that declaration in the function pointer typedef, then declare the actual struct using the typedef'd function pointer.
This code compiles with the intel compiler on linux (and seems to do the intended thing) but the Visual compiler throws an error:
error C2275: 'myStruct' : illegal use of this type as an expression
see declaration of myStruct
Is there a way to make the VC accept my intended construct?
typedef struct MYSTRUCT {
getSomething get_something;
};
should be
struct MYSTRUCT {
getSomething get_something;
};
struct MYSTRUCT; // Forward declare the struct
typedef struct MYSTRUCT myStruct; // define the typedef;
typedef void (*getSomething)(myStruct*); // use the typedef;
struct MYSTRUCT { // define the struct
getSomething get_something;
};
void get_property() { // use the typedef again.
myStruct *structure = NULL;
}
// Warning: I didn't actually compile that, and I'm going from memory.
Sorry. I just realized this was not a problem of my forward declaration but rather because what I really did in my actual code was this:
void get_property() {
some = assignment_statement;
myStruct *structure = NULL;
}
I.e. I accidentally put my variable declaration + definition below the first code statement. So indeed, I had oversimplified my code fragment. Sorry for this.
I need to declare a struct that both use one another.
For, example, how do I compile this?
z3 src # cat dependant.h
typedef struct egg_t egg_t;
typedef struct chicken_t chicken_t;
typedef struct egg_t {
int egg_num;
struct chicken_t chicken;
} egg_t;
typedef struct chicken_t {
int chicken_num;
struct egg_t egg;
} chicken_t;
z3 src # gcc -c dependant.h
dependant.h:6:20: error: field 'chicken' has incomplete type
dependant.h:7:3: error: redefinition of typedef 'egg_t'
dependant.h:1:22: note: previous declaration of 'egg_t' was here
dependant.h:12:3: error: redefinition of typedef 'chicken_t'
dependant.h:2:26: note: previous declaration of 'chicken_t' was here
z3 src #
You can create pointers to incomplete types (nixing the typedefs since they don't add anything):
struct egg_t;
struct chicken_t;
struct egg_t {
int egg_num;
struct chicken_t *chicken;
};
struct chicken_t {
int chicken_num;
struct egg_t *egg;
};
Of course, the right answer is to avoid this kind of circular dependency in the first place, but that's not always possible.
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).