This question already has answers here:
self referential struct definition?
(9 answers)
Closed 6 years ago.
struct node{
struct node next;
int id;
}
gives "field next has incomplete type error ".
what is wrong with this struct ?
When creating a self-referential data type, you need to use pointers to get around problems of circularity:
struct node;
struct node {
struct node * next;
int id;
}
...should work, but take care to allocate memory correctly when using it.
Why a pointer? Consider this: the point of a struct definition is so that the compiler can figure out how much memory to allocate and what parts to access when you say node.id. If your node struct contains another node struct, how much memory should the compiler allocate for a given node?
By using a pointer you get around this, because the compiler knows how much space to allocate for a pointer.
If a struct could contain another instance of its own type, its size would be infinite.
This is why it can only contain a pointer to its it own type.
Furthermore, at that point in code, the size of the struct is unknown, so the compiler couldn't know how much space to reserve for it.
You need to do a forward-declaration of node, since the compiler doesn't know node yet while it's processing its definition.
You probably meant to store a pointer, not a node object itself.
Try this:
struct node;
struct node{
struct node *next;
int id;
};
Some uses of incomplete types are ill-formed, such as when you try to declare an object of an incomplete type. However, you can declare a pointer to an incomplete type (for example). In this case that is just what is needed here:
struct node{
struct node *next;
int id;
};
The problem is, when the compiler reaches this line:
struct node{
struct node next; /* << this line */
the compiler actually doesn't know what is struct node, because you're defining struct node.
In general, you cannot use a type which is not defined or incomplete.
In order to work, you should write:
typedef struct _node{
struct _node* next;
int id;
}node;
Related
Sorry first for my bad English. I'm begginer in C, trying to make a Singly Linked List.
This is my setup of the List:
#include <stdio.h>
#include <stdlib.h>
typedef int Element;
struct
{
Element Data;
struct Node *Next;
} Node;
typedef struct Node *Position;
typedef Position List;
This is how I initialize this Struct (i dont know if this function is wrong):
void resetList(List *L)
{
*L = (struct Node *)malloc(sizeof(Node));
};
My problem is, wherever I used the (->), I will got this error
error: invalid use of undefined type ...
the compiler mark the error at any (->) in my code. For example:
int isEmpty(List L)
{
return (L->Next == 0);
};
will get the error at (->).
I know my code is so dump. Please help me. Thanks.
My problem is, wherever I used the (->), I will got this error
Your struct needs to be defined as a type and at the same time a self-referencing type, able to point at a variable which is of the same type as itself. In can be done like this:
typedef struct Node
{
Element Data;
struct Node *Next;
} Node;
Where the first Node is a struct tag, which is a name allowed to co-exist with the type name Node later defined at the } Node;.
Hiding pointers behind a typdef like typedef struct Node *Position; is horrible practice, because it achieves nothing except making the code much harder to read for everyone including yourself. There's no need for a typedef at all here, just declare a variable Node* Position.
Similarly, drop the typedef Position List;, creating new types just for the heck of it only creates clutter.
This is how I initialize this Struct (i dont know if this function is wrong):
The reason why you aren't sure, is because of all the obscure typedefs. Consider rewriting the function as:
void resetList (Node** list)
{
*list = malloc(sizeof(Node));
};
The reason why it has to be a pointer-to-pointer is explained here: Dynamic memory access only works inside function
As for what this function does, resetList is a very weird name for a function allocating a single node. I would expect it to delete the previous list if present and then maybe allocate a new node.
In general, the first declaration of struct Node is not correct. If you specify the name of the structure at the end of its declaration, you are not specifying data type, but you create only the struct variable. Therefore, the compiler doesn't know how to allocate struct Node *Next; item in your struct.
You can simply repair your code by moving the name of the structure:
typedef int Element;
struct Node
{
Element Data;
struct Node *Next;
};
typedef struct Node* Position;
typedef Position List;
i tryied to write the hashtable and found this github repository: enter link description here. I'm having difficulty understanding this code:
struct entry_s
{
char* key;
char* value;
struct entry_s* next;
};
typedef struct entry_s entry_t;
struct hashtable_s
{
int size;
struct entry_s** table;
};
typedef struct hashtable_s hashtable_t;
I've two questions:
Why there using the typedef struct entry_s entry_t; instead of
struct entry_s
{
char* key;
char* value;
struct entry_s* next;
}entry_t;
because if i use second way i will have error.
What does that code mean: struct entry_s** table;
I know this question can be so eazy to answer, but I will be glad if you help me
Why there using typedef struct entry_s entry_t; instead of
struct entry_s
{
char* key;
char* value;
struct entry_s* next;
};entry_t;
The syntax you give is not correct and does not do what you think. The last line, };entry_t;, is regarded as a new statement, because your compiler expects that after each ; there will be a new one. What you want to write is the following code:
struct entry_s
{
char* key;
char* value;
struct entry_s* next;
} entry_t;
This structure is a linked list, you can see that one of the fields (the last one) uses the same structure to keep a data. In a more abstract way, you can see this code such as:
struct my_linked_list_s
{
T data;
struct my_linked_list_s *next;
};
In C, a recursive data type (i.e. one that is used in its own definition), requires a pointer (for reasons of measuring the size of the structure*), which is why we see one in the next field. Then, in order to distinguish between the "internal" use of the structure and its external use, we define an alias type:
typedef struct my_linked_list_s my_linked_list_t;
Or, in your case:
typedef struct entry_s entry_t;
This is not a necessary thing though, but your implementation has chosen to do so. You can see the naming convention: _s for "structure" and _t for "type".
Because if i use second way i will have error.
You should read your compiler's error messages more carefully, it would have helped you understand what's wrong.
What does that code mean: struct entry_s** table;
This is an array of pointers. Your implementation has chosen to use linked lists and pointers, this function clearly describes the adding part.
For a better overview of the C hash tables, check out this answer.
*To determine the size of a structure (sizeof(struct my_struct)), the sum of the size of all fields is used. If we were to determine the size of a recursive structure without using a pointer (a pointer has a fixed size, for any type of data), then the structure would have an infinite size. To avoid this problem, we therefore use a pointer.
The answer for the second question is you are decalring an array of pointer that can store the pointers of the type struct entry_s** .
I'm using this structure as a linked list:
typedef struct Node{
int value;
struct node_t* next;
}node_t;
And everything works fine until I put struct node_t* next before int value field, then I have a lot of trash values working with that structure.
Is it about wrong implementation or something else in the code?
You are calling your structure Node and defining a node_t type. Then you are using node_t as if it was the name of the structure and not the type.
Try this
typedef struct node {
int value;
struct node *next;
} Node;
Or
typedef struct node Node;
struct node {
int value;
Node *node;
};
If you call it struct Node, then
struct Node {
int value;
/* The compiler doesn't know what `struct Node' is yet */
struct Node *next;
/* But you can always declare pointers, even of types the compiler
* doesn't know everything about. Because the size of a pointer
* does not depend on the type of the pointee.
*/
};
In your example, it's even worse. You typedefed something that is a new type as the compiler understand it, to use it you MUST not use struct. The whole idea behind typedefing is that you DEFINED a new type, so suppose the following
typedef struct Node node;
then to declare a pointer of type node (note, again node IS A TYPE),
node *anode;
but you attempted something like
struct node *anode;
and it's wrong because there is no struct node in the code above, it's struct Node.
Another mistake in your code is that, the node_t type does not exist when the compiler finds the
struct node_t *next;
which is already wrong because if the type were defined before the struct which is possible like this
typedef struct Node node_t
it'd still be wrong to use struct on the node_t type, because for the compiler node_t is not a struct it's a new type, which in turn is simply an alias for struct Node.
Typedefing structures in my experience is more trouble than benefit anyway. And it's not so hard to type struct Something instead of just Something. It also has the benefit of being more explicit, so if another programmer reads your code, they will immediately know that Something is a struct.
Note: I deliberately changed the name to node because it's considered bad practice to suffix your own defined types with _t. It's not necessarily a bad thing, but over the years that I've been working with this I developed some habits and one of them is not to use _t as a suffix for my own defined types. Which by the way only exist in my code if they will improve readability a lot. Otherwise I simply use the name of the structure with the struct keyword.
You are using a non existing type node_t. The type doesn't exist because the type struct Node is not even complete and you are using it's alias. Another thing to remember while using typedefs with structures don't use struct keyword along with alias
eg.
/* This is correct */
typedef struct Node
{
int x;
struct Node *next;
} node_t;
/* while these are incorrect */
/* Prefixing struct keyword to a typedef'ed type */
struct node_t *listhead;
/* The type is inclomplete and you are using an alias of the type
which doesn't even exist */
typedef struct Node
{
int x;
node_t *next;
};
You are trying to create a pointer to the structure which you are yet to create. So, it should have been,
typedef struct Node{
int value;
struct Node* next;
}node_t;
The follwing declaration is valid.
struct node
{
int a;
struct node *next;
};
However, when we define the following, it gives error.
"error: field ‘next’ has incomplete type"
Why is it so?
struct node
{
int a;
struct node next; /* Not a pointer */
};
node in struct node is a "struct tag", which at the point you write it creates an "incomplete type": a struct variable which is not at this point declared, but not defined. The type is not complete before the final }; of your struct.
In C, an incomplete type can be referenced even before it is fully defined, by using a pointer to that type. You can however not allocate a variable (instance) of that type, because the actual struct definition is yet to be defined. (It works exactly like abstract base classes in C++, if you are familiar with those.)
So when you write
struct node {
int a;
struct node *next;
};
the row struct node *next means "here is a pointer to a struct node, even though I have no idea how that type is defined yet". But you cannot declare a variable of type struct node inside the struct definition of that very same type, simply because you cannot use something before you have created it.
You can't have structure that contains itself as a member:
struct node
{
int a;
struct node next;
};
Think about this question: if it is possible, what is the size of such structure? struct node contains struct node next as a member, then the member next would contain a member of type struct node as well, and so on and on and on... The size would be infinite.
Your second declaration would define a struct which is infinitely deeply nested, which is impossible.
This is the same case as with forward declaration of class/struct type:
struct node;
struct node* node_ptr; /* is valid */
struct node node_instance; /* is invalid */
So struct node; basically says: hey there is a structure defined somewhere outside this file. The type is valid, pointers may be used, but you cannot instantiate the object.
This is because the size of the pointer is known and is specific to the target architecture (e.g. 32 or 64-bit). The size of the structure is unknown until declared.
When you declare the type completey, then you will be allowed to declare the object of that type:
struct node {
int a;
struct node* b; /* this will work, but the size of struct is unknown yet */
}
struct node* node_ptr; /* this works always with full and forward declarations */
struct node node_object; /* now, the size of struct is known, so the instance may be created */
it should be like this:
struct node {
int a;
struct node *next;
};
this works,
but
struct node {
int a;
struct node next;
};
cannot be understood by the compiler as node becomes recursive structure, and the compiler does not know how much memory to allocate for node.
However, if you use a pointer, it understands that the size of a pointer is equal to size of the memory to be addressed, and hence reserves that space, regardless of if node is a complete struct.
Pointer store address, struct has structure. If declared like struct it would be recursive and infinite. If declared like pointer it refers to other structure somewhere else.
Infinite nodes inside a node? Does that make sense? What will be the size of "struct node"?
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Circular definition in C
typedef struct{
node *next;
node *last;
} doubleLink;
typedef struct{
doubleLink doubleLink;
int data;
} node;
The above is a doomed attempt to define an object with a double link.
Placing either typedef before the other would draw a compilation error of "unknown type"
One obvious recourse is to change the pointer type specifier in doubleLink to void *
But I wonder whether there are more "harmless" solutions, say, maybe
I can declare the node struct without defining it?
I'm cognizant that this must be a frequently asked question, but I don't know by what keyword can I possibly find it.
Add forward declacation of node:
struct node;
typedef struct{
struct node *next;
struct node *last;
} doubleLink;
As you use pointers, you don't need to have this type completely defined before the definition of doubleLink.