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?
;
after themMight 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.