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.
Related
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;
I read all the other posts with no success yet (eg forward declaration of a struct in C?)
There are two header files with functions which reference structs from each others' headers.
Forward declaration isn't working...surely because i'm still doing it incorrectly:) Thoughts?
foo.h:
typedef struct{
...
}foostruct;
extern foostruct fooStruct; //this struct used in foo.c and other c files
typedef struct barstruct; //attempt at forward declaration
void fooFctn(barstruct *barVar); //needs definition from bar.h
bar.h:
typedef struct{
...
}barstruct;
extern barstruct barStruct; //this struct used in bar.c and other c files
typedef struct foostruct; //attempt at forward declaration
void fooFctn(foostruct *fooVar); //needs definition from foo.h
The error is
error: useless storage class specifier in empty declaration [-Werror]
src/search.h:123:18: error: unknown type name 'foostruct'
Since these structs were typedef-d originally i also tried just "foostruct;" without the identifier which (of course) doesn't work, likewise declaring "typedef struct fooVar foostruct" generates a redefinition error.
In your foo.h, this code:
typedef struct barstruct;
is a degenerate typedef that announces that struct barstruct exists, but does not give an alternative name for it (hence the 'useless storage class specifier in empty declaration' warning/error). You need:
typedef struct barstruct barstruct;
Then the code will work properly in foo.h. The corresponding change is needed in bar.h for struct foostruct.
However, that still leaves you with a problem. The type barstruct declared in foo.h is not identical to the type barstruct declared in bar.h (because one is a tagged structure and one is a tagless structure). There are several ways around this. In C11 (but not C99 or C89), you can repeat a typedef if they're identical.
You would therefore have the two typedef lines:
typedef struct barstruct barstruct;
typedef struct foostruct foostruct;
at the top of the headers, and then define in bar.h:
struct barstruct { … };
and in foo.h:
struct foostruct { … };
If compatibility with earlier versions of C is important, then you need to consider using struct barstruct and struct foostruct in the function declarations:
foo.h
typedef struct foostruct foostruct;
struct foostruct
{
…
};
extern foostruct fooStruct;
struct barstruct;
void fooFctn(struct barstruct *barVar);
and analogously for bar.h. This will also work with C11, of course.
Properly typedef your struct should resolve your problem.
typedef struct foostruct foostruct;
Structures and tags
struct { ... }; is an anonymous structure. It is only useful with typedefs, and only when that typedef name is used and declared in that one file. In other words, it cannot be used with forward declarations.
However, struct X { ... }; is a structure of type struct X. It can be used for forward declarations. Note that X is just the tag name used to denote a specific structure type, not the actual type. The tag name is used to distinguish between other declared structure types. This confuses people sometimes, so an example might help. Note that all of the declared structure types are different:
/* Declare an anonymous structure. */
struct {
int n;
};
/* Another anonymous structure. It in different from the previous one. */
struct {
double d;
};
/* Declare a structure of type `struct bar'. */
struct bar {
int n;
};
/* Declare a structure of type `struct foo'. */
struct foo {
int n;
};
/* Declare a variable `var' of type `struct foo'. */
struct foo var;
/* Unless a typedef for the `foo' type exists, or a preprocessor macro is used to replace `foo' with an actual type, this is a compilation error. */
foo var2;
Note that if you attempt to declare two structures with the same tag name, it is an error.
typedefs
The form for a typedef is the same as for a variable declaration with no initializer:
typedef TYPE NAME;
For example:
typedef int Integer;
declares the Integer type to be the same as int. The same can be done with structures:
/* Typedef'd anonymous structure */
typedef struct {
int foo;
} fooBType;
/* Typedef'd `struct foostruct' structure */
typedef struct foostruct {
int foo;
} fooGType;
The difference between the two:
forward declarations of the structure type referenced by fooBType in other files are not possible because the structure referenced by fooBType is anonymous
forward declarations of the structure type struct foostruct referenced by fooGType are possible because the type is able to be referenced by the structure tag and the struct keyword, as in struct foostruct or typedef struct foostruct fooGType;
I hope this helps.
I'm trying to create a struct to be used in a Linked List that looks like this:
#ifndef MYGREP_H
#define MYGREP_H
typedef struct occurrenceType Occurrence;
struct occurrenceType {
char* line;
int lineNumber;
int wordNumber;
Occurrence *next;
};
#endif
but when I try to allocate memory using sizeof(Occurrence) I get the error "Invalid application of 'sizeof' to incomplete type 'Occurrence.' I've tried several different structure declaration formats with no luck. Can someone tell me what I'm doing wrong? Thanks!
Your first struct typedef declaration:
v
typedef struct occurenceType Occurrence;
^
has one 'r' on "occurencyType" but your definition:
vv
struct occurrenceType {
^^
char* line;
int lineNumber;
int wordNumber;
Occurrence *next;
};
has two 'r's.
Struct is user defined data type in c. Before the declaration of occurrenceType you are trying to use it and hence before its declaration or definition if you try to use it then it is an error. Your code should be
#ifndef MYGREP_H
#define MYGREP_H
struct occurrenceType {
char* line;
int lineNumber;
int wordNumber;
Occurrence *next;
};
typedef struct occurrenceType Occurrence;
#endif
First declaration then use it. Another it may be some spell mismatch so try to use this
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).