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"?
Related
I have the following struct defined with the typedef keyword:
typedef struct{
int data;
NODE *next;
}NODE;
It gives me the following error when compiling:
error: unknown type name ‘NODE’
I looked it up, and found this stack overflow post, which said I should change it to
typedef struct n{
int data;
n *next;
}NODE;
I have two question about this.
First, what is the n? I thought NODE was the name of the struct, so is that a second name?
The second is, why can I put the n as a data type, but not NODE?
NODE is not the name of the struct. It's a typedef, i.e. an alias for the struct. In the first case, the struct is unnamed. In the second case, the struct is named struct n.
The reason you can't use NODE inside of the struct is because that name hasn't been defined yet at the time it is used. So you need to use the actual name of the struct (which is defined) in order to create a pointer to it.
Also note that the struct keyword is required in C when using the struct's name, i.e.:
struct n *next;
With your combined structure definition and typedef, the name NODE is not yet defined at the location when you try to use it.
typedef struct{
int data;
NODE *next; // name NODE used here
}NODE; // name NODE defined here
You can do the typedef before the structure definition to use it for a pointer.
typedef struct n NODE; // NODE defined as incomplete type
struct n {
int data;
NODE *next; // use as pointer is OK
};
// from here NODE is completely defined
But you cannot define a variable or structure field of type NODE before the structure is really defined.
typedef struct n NODE;
#if 0
// does not work because NODE is an incomplete type here
struct wrapper {
NODE node;
};
#endif
// using a pointer to an incomplete type is OK
struct n {
int data;
NODE *next;
};
// works
struct wrapper {
NODE node;
};
You can use
typedef struct n{ // type "struct n" known here
int data;
struct n *next; // use known type
}NODE; // type alias NODE known here
because the type struct n is already known when you use it for the pointer.
Note that in C you have to use struct n *next (in contrast to C++).
Why I can compile below code without any declaration?
struct node *n;
int main()
{
return 0;
}
I did'nt include any header.
Is this normal?
The pointer definition acts as a forward declaration of struct node. Using such a declaration is allowed as long as the pointer isn't dereferenced before the actual struct definition appears.
This is necessary to allow constructs like this:
struct list_node {
int value;
struct list_node *next;
};
This is a typical definition of a node in a linked list. The next field is of type struct list_node *, but at this point struct list_node has not yet been fully defined. If such forward declarations were not allowed, such constructs would not be possible.
You can also use such a pointer to pass to a function and get a value returned. For example:
struct node *n = new_node();
set_node_value(n, 1);
These two function could be defined in a separate source file where the full definition of struct node is known. The structure in this case is an opaque type that users of a library don't need to know the details of.
I'm new to structures in c, I've been researching the difference between the . operator, and the -> operator. But I can't seem the find resources that explain what I want to know. So, why if I make structure without typedef, can I use it directly such as "header.first = x", and not having to say "struct header varName"? Also, what is the difference between the . and -> in this example, because it seems in this case I can use them interchangeably.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node* next;
}node;
struct header{
int count;
node *first;
}header;
int main()
{
node *curptr = (node*)malloc(sizeof(node));
printf("%p\n",curptr);
header.first = curptr;
printf("%p\n",header.first);
header.count = 10;
printf("%i\n\n\n",header.count);
node* current = (node*)malloc(sizeof(node));
current->data = 5;
current->next = NULL;
printf("%i\n",current->data);
printf("%p",current);
}
struct header { ... } header; is simultaneously creating the struct type (struct header) as well as creating a global variable (named header, of type struct header). It is equivalent to doing:
struct header { ... };
struct header header;
When you write header.first = x, what you're doing is just modifying the global object named header.
typedef struct node { ... } node; is simultaneously creating the struct type (struct node) as well as a typedef to it (node). It is equivalent to doing:
struct node { ... };
typedef struct node node;
As for . vs ->: a->b is equivalent to (*a).b. It's just syntactic sugar.
struct in c is a place in memory which is big enough to keep data for all its fields. As with any other objects in 'c' you have a choice to use it as a variable or use a pointer to it. A pointer is essentially a memory address of this variable.
Also, every variable in 'c' has a type. The latter behaves like a template for creating variables and check their usage.
So, in the following example you create a struct type struct header and describe what it contains.
struct header{
int count;
node *first;
};
Now, using the type, you can create the variable named my_header:
struct header my_header;
or, as in your example, variable header.
struct header header;
As in you example you can combine both into a single statement.
Now, if you created a variable of type 'struct header', you can access its members using the . operator. The following operator will cause 'c' to access member count of your struct variable. It will calculate correct place in memory to put '10' into it.
header.count = 10;
as for pointers, you can create a variable which will keep an address to your object. In 'c' it needs to know what type of object it points to. So, the pointer ptr in the following example is assigned address & of the variable header.
struct header *ptr = &header;
Now you can use the pointer to access fields in the header, but it requires a different syntax ->. so, the following statement will be equivalent to the previous one:
ptr->count = 10;
Note that in both cases '10' was assigned to absolutely the same object, field of the variable 'header'.
Also to make life easier ant to stop typing struct every time, you can use the typedef operator to declare a named type, i.e.
typedef struct node myNodeType;
typedef struct node node;
now you have to 'named' types: myNodeType and node which are the same. you can use them to declare variables and pointers:
myNodeType var1; // variable
node *next; // pointer.
and as in case with variable declaration, you can combine it with struct declaration as in your example.
And malloc just allocates a chunk of dynamic memory and returns its address, aka pointer to it. so, node* current = (node*)malloc(sizeof(node)); just assigns address of allocated memory to the pointer current.
Hope it helps a bit.
This question already has answers here:
typedef struct vs struct definitions [duplicate]
(12 answers)
Closed 7 years ago.
I am getting a hard time understanding this sample of code:
typedef struct node
{
int data;
struct node * next;
} node;
typedef node * nodepointer;
So, we are building the struct node using typedef... I assume we are doing this in order to initialize the struct without the "struct" keyword being necessary.
I want to ask why in the struct definition we used the name "node" twice (at start and end).
Secondly what typedef node * nodepointer; points to. Is it necessary to use typedef in this case? Is this expression node * nodepointer; not equal?
First off, let's be clear here: a typedef isn't a declaration of a variable. It simply aliases a new type name to an existing type specifier.
typedef <type specifier> new_type_name;
So what's going on here can certainly be deceiving to the untrained eye.
struct node itself is a struct called node with the two properties int data and a struct node *next.
I'll go more into next in a moment, but for now this is simple enough.
Then, the surrounding typedef takes that struct and gives it the name node. Why is this, you might ask?
This is due to the fact that in C (unlike C++) using structs by their tag name requires prefixing the type with struct.
struct Foo {
// ...
};
Foo bar; // ERROR
struct Foo bar; // OK
Using a typedef, we alias the struct with a typename, called node. This example should make it a bit more clear.
typedef struct Foo {
// ...
} FooType;
Foo bar; // ERROR
struct Foo bar; // OK
FooType bar; // OK
struct FooType bar; // ERROR
Keep in mind you can define structs without tags, and thus typedef them.
typedef struct {
// ...
} FooType;
FooType bar; // OK
Though I'll explain why you can't do this in your example.
The property struct node *next in your example is an incomplete type. Incomplete types, simply put, are types that have been declared (given a name and a type, i.e. struct node;), but not defined (given a 'body', i.e. struct node { int foo; };).
Incomplete types cannot be used until they are defined, unless you're pointing to them.
struct Foo;
struct Foo bar; // ERROR: Foo is not defined.
struct Foo *bar; // OK - it's just a pointer. We know the size of a pointer.
struct Foo {
// ...
};
struct Foo bar; // OK - it's defined now.
So by the type struct node *next is declared, we already have the declaration of struct node but not the definition, which makes a pointer to struct node possible.
You can also infer, too, that using struct node directly would not work:
struct node {
struct node next; // ERROR - `struct node` becomes infinitely big
struct node *next; // OK - a pointer is usually 4/8 bytes (we at least know its size at this point)
};
To answer your last three questions:
What [does] typedef node * nodepointer; [point] to[?]
Nothing. It's just an alias (a label, or a 'nickname') to another type. It simply says that the type nodepointer is really a node *.
This also means anything that requires a node * can thus use a nodepointer, and vice versa.
Is it necessary to use typedef in this case?
Not necessary, no. You could just as well use node * everywhere instead of nodepointer. Most coding standards frown upon typedefing types to their pointer types (like your example) because it adds confusion to the code base (as you have demonstrated by this very question! :))
Is [the] expression node * nodepointer; not equal?
Nope. Again, remember typedef simply specifies another way to reference the same type. It doesn't actually create any memory, rather gives a new name to an existing type.
This struct is self referential which means it contains a pointer to itself.
if you don't use tag node, How will you specify pointer type later. Hence first node is required
struct node {
struct node *ptr;
};
// you can do this way too
typdef struct node node;
The last node is required for completing the typedef.
By typedef node * nodepointer;, Now you can use nodepointer to mean node*. Wherever node* occurs, you can simply replace with nodepointer
Is it necessary to use typedef in this case?
It is upto you,
Is this expression node * nodepointer; not equal?
No, this only declares nodepointer to be pointer variable whereas typedef creates alias of type, node * by the name nodepointer.
The question is that you are doing two things at once: declaring struct type and typedefing that struct to a name.
For typedef the syntax is
typedef <some type> name;
where some type may be a simple type, like int, long, etc. or a complex one like struct foo, and this regardless of wether struct foo has been declared before or it's being declared at that very point.
So
typedef struct foo { int bar; } foo;
Corresponds to
typedef <some type> name;
where <some type> is struct foo { int bar; } and name is foo
As to the second question,
In this case <some type> is node * and name is nodepointer, so
typedef node * nodepointer;
is typedefing a nodepointer as a pointer to a node (which you have typedefd just before to be a struct node { ... })
typedef struct node
int data;
struct node * next;
} node;
The node in the first line is the tag of the structure.
The node in the last line is the name of the type.
These two do not have to be identical.
If you want them to be different the code will be as follows.
typedef struct helloNode
int data;
struct helloNode * next;
} node;
The name of the type is node. The name of the structure is helloNode
For a more technical explanation, these two nodes are in different namespaces. and can have different values.
From section 6.3 of http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
If more than one declaration of a particular identifier is visible at any point in a
translation unit, the syntactic context disambiguates uses that refer to different entities.
Thus, there are separate name spaces for various categories of identifiers, as follows:
— label names (disambiguated by the syntax of the label declaration and use);
— the tags of structures, unions, and enumerations (disambiguated by following any32)
of the keywords struct, union, or enum);
— the members of structures or unions; each structure or union has a separate name
space for its members (disambiguated by the type of the expression used to access the
member via the . or -> operator);
— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as
enumeration constants).
For the struct, you are defining your structure name (before the braces) and then the type name (after the braces):
typedef struct node {
int data;
struct node* next;
} node;
The next one creates another type, a pointer to nodes:
typedef node* nodepointer;
Both can now be used to create variables:
node myNode;
nodepointer aPtr;
Daleisha said correctly that you need the struct tag in order to declare the pointer next which points to just these structures. You cannot write that type name down before it is introduced. Another possibility is to forward-declare the struct:
struct node;
typedef struct node node;
struct node
{
node *next;
int i;
};
But that introduces rather more mentionings of one node or another.
As a side effect, introducing the struct tag "node" makes it possible to still write the normal struct node, which the typedef alone would not make possible.
The second typedef is also still a typedef, it doesn't introduce a variable but a type name. After all the declarations in your source snippet you can say
struct node *np1;
node *np1;
nodepointer np1;
These are all equivalent.
The co-existence of the two type names node and struct node is possible because "struct tags" (like the "node" in "struct node"), as they are called, are held separately from other names and can therefore be used to name something else, additionally, without collision. To typedef a struct so that the new type has the name of the struct tag is a common example, but the name "node" could be used for anything else instead (an int variable, whatever).
struct node
{
int data;
node* pointerToNextNode;
};
Here pointerToNextNode is the type of struct node, and it is declared inside the struct.
How does the struct know the type of next pointer of its own type - when it itself hasn't been formed yet?
There is no keyword extern used. How does this work?
It doesn't need to know the structure, it's enough to know the type name, namely struct node — and that has already been defined.
Same result you can obtain by forward type declaration:
struct node; // declare the struct not defining it
struct node *pointer; // declare variable
void foo()
{
if(pointer != NULL) // OK, we use the pointer only
if(pointer->x == 0) // invalid use - struct contents unknown yet
return;
}
struct node { // supply a definition
int x;
};
void bar()
{
if(pointer != NULL)
if(pointer->x == 0) // OK - struct contents already known
return;
}
Here pointerToNextNode is the type of struct node
No, it's not. It's of type struct node *
struct node* pointerToNextNode; allocates memory for a pointer variable of type struct node.
It does not allocate memory for struct node, so, till point, it does not need to know about the size and representation of struct node. Only the (data)type name is sufficient.
Also, it's worthy to mention, without a typedef in place, node* pointerToNextNode; should not be valid. It should be written like below
typedef struct node node;
struct node
{
int data;
node* pointerToNextNode;
};
BTW, private: is not C thing, if i'm not wrong.
for me this doesn't compile using CC -- and exactly because of what you said.
you would have to use struct node * to make the compiler aware you want memory for a pointer