Understanding typedef with struct [duplicate] - c

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).

Related

Why I can use pointer of structure type before delaration

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.

difference between structure operators in c

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.

Self referring structure declaration

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"?

What is exactly being declared by typedef?

typedef struct nodetype node;
typedef node *link;
struct nodetype
{
int dat;
link ptr;
};
typedef link *stack;
In the code above I am a little confused on what is all being defined.
I understand what typedef does, but I am still wondering what exactly is being defined by typedef node *link; Is it defining a pointer to a node? Also I have the same question for the typedef link *stack;
The typedef lines are not creating anything. typedef is used to give new names for types, they are not declarations or definitions of variables, so nothing is really creating at this moment.
typedef node *link;
means link is another name for the type node *. Only when you use it like:
link link_varialbe;
A variable of type link (the same as node *) is created.
node is an alias for the type struct nodetype; link is an alias for the type node *, meaning it's also an alias for the type struct nodetype *.
stack is an object of type link *, which is the same as type node **, which is the same as type struct nodetype **.
This is a horrible example of how to use typedefs, precisely because of the confusion it is causing you. It's creating a bunch of different names for the same thing with no good reason, and it's hiding a pointer in one of typedef names which is almost always bad juju.
typedef defines an alias for a given type.
Its merit is to give some special meaning to the elements of your code.

typedef confusion in C

I'm having a hard time understanding the typedefs in this C structure.
typedef struct node {
int value;
list rest;
} node;
typedef struct node *list;
What's the difference between the "node" typedef declaration and the "list" declaration? Why is list prefaced as a pointer? Isn't "node" a pointer as well? Why can't I simply say "typedef struct node list" and omit the asterisk? I've been searching everywhere and I can't really find a satisfactory answer.
The first typedef defines node as an alias for struct node, to allow you to refer to it simply as node without writing struct node every time (in C "regular" type names and struct names live in two different namespaces). It's equivalent to:
struct node
{
int value;
struct node* rest;
};
typedef struct node node;
The second typedef, instead, defines list as an alias for node *, i.e. defines the type list as a pointer to a node structure.
(by the way, personally I find that this is very bad style: hiding pointers inside typedefs is almost always a bad idea; one can argue that a pointer to the first element in a list could be identified as the list, but the usage of list even for the rest pointer is IMHO not very nice)
node is not a pointer; it is a struct. list is a typedef for a pointer to node.
You typedef a struct in C to avoid typing struct node ... everywhere.
Whether or not this is good practice is questionable (most will agree that hiding a pointer type behind a typedef, unless it is truly opaque, is a bad idea), but that's the gist of it.
The first declaration says that a node is the structure. The second says that a list is a pointer to a node.
So, this would be proper code using those declarations:
list x;
node n;
x = &n;
Declaring an item using typedef struct node list is not correct. The typedef statement declares a new type. The keyword typedef is not part of the type's name.
node is a struct, which is (confusingly) named the same thing as struct node. list is a pointer to struct node. So the following are equivalent:
struct node *a;
node *a;
list a;
node is just a synonym for struct node
list is a pointer to a struct node (or node)
Each node instance contains a list pointer which enables you to build data structures such as (singly) linked lists, etc.

Resources