I am trying to define two structures in C when the second struct uses the first as an array member and has two pointer members of itself.
Visual Studio does not like my code:
syntax error : '}'
syntax error : identifier 'tokenListNode'
syntax error : missing '{' before '*'
any idea how to solve this?
--> Please note that the errors appear with or without the declarations I added at the beginning of the code.
--> In addition, if someone can explain to me what is the difference between the identifier
before and after the struct's curly brackets, I'll be grateful.
Below is the code:
#define ARRAY_SIZE 100
struct tokenListNode;
struct TOKEN_LIST_NODE;
enum TOKEN_TYPE
{
id = 0,
INT_NUM,
INT_REAL,
ASSIGNMENT_OP,
RELATION_OP,
ARITHMETIC_OP
} tokenType;
typedef struct TOKEN
{
char* lexema;
enum TOKEN_TYPE type;
int lineNumber;
} token;
typedef struct TOKEN_LIST_NODE
{
token tokenArray[ARRAY_SIZE];
tokenListNode* prevNode;
tokenListNode* nextNode;
int tokenCounter;
}tokenListNode;
You do not define tokenListNode until after you use it. Change to the following:
typedef struct TOKEN_LIST_NODE tokenListNode;
struct TOKEN_LIST_NODE
{
token tokenArray[ARRAY_SIZE];
tokenListNode* prevNode;
tokenListNode* nextNode;
int tokenCounter;
};
The definition of a structure is composed of the keyword struct; the "struct tag"; and the struct members
struct tag { int member1; /* &c */ };
You can leave the tag out and create an unnamed structure ... why you would do so is another matter: you can't refer to the structure without a struct tag!
struct { int member1; /* &c */ };
Also, you can take any type and give it another name using typedef
typedef old_type new_name;
as in
typedef struct tag { int member1; /* &c */ } tag;
/* <------------ old type ------------> <new name> */
The above line defines a struct (named struct tag) and, at the same time, gives that type a new name: tag
what is the difference between the identifier before and after the struct's curly brackets
That's the result of mixing definition of struct and typedef. The name before the {} is the "tag" of the structure, the name after the {} is the new name for the type being typedef'd.
You need to use the struct tag instead of it's typedef'ed version when referring to itself.
struct TOKEN_LIST_NODE
{
token tokenArray[ARRAY_SIZE];
struct TOKEN_LIST_NODE* prevNode;
struct TOKEN_LIST_NODE* nextNode;
int tokenCounter;
};
Related
I have the following code where a struct field depends on a struct field that is not declared yet, because that struct in turn might depend on the struct that I am trying to declare.
How can I design this so that it compiles? Or am I missing an obvious way to get rid of the union struct for keeping several struct definitions together?
typedef struct expression {
expression_type type;
union {
bool_expression bool;
identifier_expression ident;
integer_expression _int;
prefix_expression prefix;
infix_expression infix;
// TODO: Fix this
if_expression _if;
};
} expression;
typedef struct statement {
token token;
identifier name;
expression * value;
} statement;
typedef struct block_statement {
token token;
statement *statements;
} block_statement;
typedef struct if_expression {
token token;
expression condition;
block_statement *consequence;
block_statement *alternative;
} if_expression;
You can't, in this case.
if_expression contains an expression which in turn contains an if_expression. If you solve this problem by using pointers, you can reorder your definitions and use struct expression* to create a pointer to a struct that has not yet been defined.
You better remove the typedefs, at least initially, so you can better understand your types.
You should change your structs to point (rather than include) other structs, for example:
struct if_expression {
/* struct? */ token *token;
struct expression *condition;
struct block_statement *consequence;
struct block_statement *alternative;
}
Of course that will impose some judiciously use of malloc() and free() calls. In some cases you can later revert to inclusion (like token above, as it isn't expected that it points to your other structs, and copying tokens around is - perhaps - a cheap operation).
For the circularity of references you can forward declarations in C, that is you tell the compiler "hey, there is a struct named expression, whose internal structure you don't know yet, but bear with me, you will soon":
struct expression;
If you later decide to use typedef - so your code gets more streamlined - bear in mind that the structs can have a name, and typedefs define names, and those names don't share the same namespace. In examples:
typedef struct {
/* ...internal structure omited... */
} type_a;
typedef struct type_b {
/* ...internal structure omited... */
} type_b;
typedef struct struct_c {
/* ...internal structure omited... */
} type_c;
Here type_a is a type whose definition is an anonymous struct. And type_b is a type whose definition is struct type_b, that is a named (type_b) structure. And type_c is a type whose definition is struct struct_c, that is a named (struct_c) structure.
Now put it all together, you can:
/* forward all your structs */
struct expression;
struct if_expression;
struct block_statement;
/* typedef them all */
typedef struct expression expression;
typedef struct if_expression if_expression;
/* actually define them */
struct expression {
/* ... */
}
As a footnote, you can learn a lot about C language by understanding the difference between declaration and definition.
If you change expression condition; to expression *condition; in if_expression, and forward declare expression — typedef struct expression expression; at the top and then place struct expression { … }; at the bottom, the code should be OK.
/* Placeholder typedefs for undefined typedef names */
typedef int token;
typedef int identifier;
typedef int bool_expression;
typedef int identifier_expression;
typedef int integer_expression;
typedef int prefix_expression;
typedef int infix_expression;
typedef int expression_type;
/* The fixed code starts here */
typedef struct expression expression;
typedef struct statement
{
token token;
identifier name;
expression * value;
} statement;
typedef struct block_statement
{
token token;
statement *statements;
} block_statement;
typedef struct if_expression
{
token token;
expression *condition;
block_statement *consequence;
block_statement *alternative;
} if_expression;
struct expression
{
expression_type type;
union
{
bool_expression bool;
identifier_expression ident;
integer_expression _int;
prefix_expression prefix;
infix_expression infix;
if_expression _if;
};
};
expression expr = { 0 };
This compiles.
I am writing a game in C. But I keep getting a number of errors. One prominent one is this. "Illegal Identifier: X" where X is the type of a variable inside a structure. An instance, Illegal Identifier: MapItem, is caused by the following code
typedef struct MapItem{
int item;
int count;
};
typedef struct MapTile{
MapItem item;
int x;
int y;
int tile;
Direction dir;
int drop;
};
The error is attached to the first line inside the MapTile struct. I would like to know why this error is occurring, and how to fix it.
The code segment was taken, in exact order, from map.h. Direction is an enum declared earlier in the same header.
Thank you all for answering. However, I did receive the answer I needed 4 hours ago.
Your typedef are incorrect. The syntax is:
typedef type typealias ;
So:
typedef struct
{
int item;
int count;
} MapItem;
typedef struct
{
MapItem item;
int x;
int y;
int tile;
Direction dir;
int drop;
} MapTile;
Note that types being aliased here are anonymous structs, the struct-tag is only required for self-referencing structs.
typedef is used to create an alias to another type (existing or defined in the same typedef statement).
Its general format is:
typedef existing_or_new_type alias;
The aliased type in your typedef is the new struct MapItem defined in the typedef statement but the alias is missing. This is the cause of the error.
You can use:
typedef struct MapItem {
int item;
int count;
} MapItem;
This statement declares the new type struct MapItem (the struct keyword is part of the type name) and the new type MapItem that is an alias of struct MapItem. This means that everywhere you can or have to use struct MapItem you can use MapItem instead.
If this seems confusing, you can use different names for the struct type and its alias. Or you can omit the name from the struct definition at all:
typedef struct {
int item;
int count;
} MapItem;
This way, MapItem is the name of an anonymous struct type and it is the only way to declare variables of this type.
Is the following, at file scope, a type declaration or an unnamed variable?
struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
If it is a type definition, then what is the difference with:
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
?
(Background: see my answer at Changing a variable from global to local - C, where I believe the first introduces an unnamed variable that is then optimized away by the compiler.)
Note: the question has been flagged as a possible duplicate of In what scope is a struct member identifier put? but I believe I am not asking a question about the scope of the members but about what the declarations actually create. However. answers to Difference between 'struct' and 'typedef struct' in C++? do explain my question.
As per the C standard, a structure declaration in the form like
struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
is the declaration of a type. Quoting C11, chapter §6.7.2.1
The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit. The struct-declaration-list is a sequence of declarations for the members of the structure or union. [...]
C standard does not mandate creating a variable (either named or unnamed) for that type.
In your second snippet, you actually (try to) typedef to nothing. However, if you change your snippet to the form of
typedef struct {
//.....members
} student_s ;
you'll be creating a type student_s (typedef to an unnamed structure type) which you can use later.
FWIW, we never talked about a variable being created here, anyways. It's all about types.
First declaration declares a type. After that declaration, the type struct student_s is known, and you can declare variables of that type or pointer to it :
struct student_s student1;
struct student_s *pStudent;
The second declaration is weird even if is compiles. The common usage would be :
typedef struct {
char* name;
int age;
double height;
struct student_s* next;
} studend_t;
which declares an alias student_t to an anonymous struct. It can then be used directly :
student_t student1;
student_t *pStudent;
BUT THE SECOND EXAMPLE DOES COMPILE (even with a warning) AND IS THE SAME AS FIRST ONE !
What it really does is to declare a void alias to struct student_s. The typedef is ignored and produces a warning : typedef requires a name, but as a side effect, the struct is declared, exactly as it was in first example.
So the true answer to the actual question is THERE ARE NO DIFFERENCES except for a warning.
Both are type definitions. The second one is one incomplete. It doesn't supply a name as the the argument of typedef. Much better is to use
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
} student;
Regarding the legality of
typedef struct student_s {
char* name;
int age;
double height;
struct student_s* next;
};
I've asked that as a separate question, Legality of `typedef struct foo {int bar};`
It's a type, and you can't have an anonymous instance of a struct. For comparison, this declares both the type struct_type and an instance struct_instance of that type:
struct struct_type {
/* blah */
} struct_instance;
If you wanted to declare another instance in isolation (from the type decl) you'd use
struct struct_type another_instance;
The use of typedef - if done correctly, unlike your example - just allows you to give the type another name which doesn't require the struct keyword to declare an instance:
typedef struct_type MyStruct;
MyStruct yet_another_instance;
or equivalently
typedef struct struct_type {
/* blah */
} MyStruct;
omitting the name (struct_type) gives you an anonymous struct type which can only referred to by its typedef'd name.
Note 1
Since your original struct contains a next pointer to its own type, that type must have a name at the point the member is declared. So, you cannot declare an anonymous struct with a self-typed pointer. If you give your anonymous struct type a name with typedef, that name doesn't exist until after the member declaration, so can't be used there.
typedef struct /*S*/ {
struct S *next; /* T doesn't exist yet, so without S, you can't declare this */
} T;
Note 2
You can declare an anonymous instance of an anonymous union, as a member:
struct S {
union {
int i;
unsigned u;
};
};
struct S s;
s.i = -1;
printf("%x\n", s.u);
but that's a very special case. I took the remark about this out of the main argument, in case it was misleading.
struct A { ... }
creates struct 'A' visible in struct namespace (which has nothing common with C++ namespaces). So, to access struct you have to use struct keyword;
struct A a;
When defined with typedef struct
typedef struct A { ... } B;
becomes visible and bound to B, and you can easily create struct like common variable of type B
B a;
Please, correct me someone, if I am wrong.
The difference is that with the first example, you have to declare a new variable like this: struct student_s variable;, however with the second example, you may simply do student_s variable;.
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);