Suppose we have a stack as defined below:
typedef struct node
{
int data;
struct node *next;
} node;
I copied this definition from a book but I'm not exactly sure what the last 2 lines do. Does the node declaration at the end have anything to do with the structure declaration or is it just an object that we are creating?
The code is equivalent to:
struct node
{
int data;
struct node *next;
};
typedef struct node node;
By separating typedef with the struct node type, it's easier to see node in your code is an alias for struct node made by typedef.
considering last two line:
1:
struct node *next;
explains: you are creating a pointer variable (i.e, next) of type struct node and capable of holding address of the same type. usually the concept comes when you want implement the stack operation dynamically.
+--+----+ +--+----+ +--+----+ +--+----+
|10|2000| |20|3000| |30|4000| |40|NULL|
+--+----+ +--+----+ +--+----+ +--+----+
1000 2000 3000 4000
it can be seen that the next part is handling the address of the another structure and hence you need the pointer of type struct node.
2:
typedef struct {
type1 fieldname1;
type2 fieldname2;
....
typeN fieldnameN;
} NEW_TYPE;
NEW_TYPE variable_identifier;
Here the NEW_TYPE is the typedef name can be used like any type.
I have tried giving the generic syntax. hope you get it.
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++).
Code without typedef (and it works):
struct Node {
int data;
struct Node *next;
struct Node *prev;
};
I'm trying to make a code using typedef for the structure "Node" in Doubly Linked List, but this does not work:
typedef struct {
int data;
Node *next;
Node *prev;
} Node;
Is there a way around this using typedef?
You can use a forward declaration of the struct
typedef struct sNode Node; // this is a typedef and a declaration of the struct
struct sNode{
int data;
Node *next;
Node *prev;
};
This way Node is known (but not defined), in the definition of your struct.
This can be compressed as it is done by Yunnosch. But then you need to use the struct Name notation inside your declaration.
This way it is possible to already use the typedefed name also the forward declaration is necessary if you have some circular dependencies in your structs.
It is also possible to use the struct name as the typedef:
typedef struct Node Node;
struct Node{
int data;
Node *next;
Node *prev;
};
I personally prefer the first style, it seems "clearer" to me, but there is nothing wrong with the second example, as long as the compiler is not from the pre-standard era (before 1989).
As Jens Gustedt pointed out the first style might be incompatible if this is included in C++.
So maybe I should change my preference to the first.
Inside the typedef, the to-be-defined type is not yet known, so you need to introduce and use a struct tag:
typedef struct Node_tag {
int data;
struct Node_tag *next;
struct Node_tag *prev;
} Node;
The Node_tag is the struct tag, because of where it is introduced (and not because of the name part "_tag"). It is not a type in itself, only the combination as struct Node_tag is a type which can be used for the struct members.
Afterwards, when the typedef is done, the type Node has been defined.
To clarify, a second typedef would be possible as typedef struct Node_tag NodeToo;. This demonstrates that the type struct Node_tag is also useable. That is why I prefer to use the "_tag" name fragment, to allow to be clear of what is used.
Inside the structure, you have indeed to use types that are already known by the compiler. A way to be compliant with this rule in your case is to use the struct Node * type after having declared typedef struct Node. In this case, even if the type struct Node is incompletely defined when the compiler encounters it inside the structure, the name is known and the compiler knows the size of a pointer (to reserve in memory), so it has no reason to complain !
Morevover it is also accepted to use the same name for the type as after struct: you can use Node for both.
Here is my suggested solution:
typedef struct Node {
int data;
struct Node *next;
struct Node *prev;
} Node;
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;
I am new to c programming and creating linked list data structure, MY teacher gave me some code which seems a bit confusing :
typedef struct node *ptr;
ptr start,current;
typedef struct node{
int value;
ptr next;
};
This code works fine and using the other functions i can create a linked list , my confusion is that, when i change the code like this:
node *start;
node *current;
typedef struct node{
int value;
node *next;
};
it doesn't work .What is wrong with this code why cant i forward declare the node pointers anymore.
typedef struct node *ptr;
ptr start,current;
typedef struct node{
int value;
ptr next;
};
The typedef for the struct itself won't work this way, I guess you're missing a node at the end (It's missing the identifier of the newly defined type).
At this point, I'd tell your teacher to please not confuse everyone by typedefing a pointer type. It's widely common to have the pointer type modifier visible on every usage, just to make it obvious it is a pointer. But now to the actual answer:
node *start;
node *current;
typedef struct node{
int value;
node *next;
};
Start at the first line: you use node here as a type identifier. But you didn't tell the compiler yet what kind of type node should be. In fact, what you're actually missing is a forward declaration. It would work like the following:
/* forward-declare "struct node" and at the same time define the type
* "node" to be a "struct node":
*/
typedef struct node node;
/* now use your type by declaring variables of that type: */
node *start;
node *current;
/* finally fully declare your "struct node": */
struct node {
int value;
node *next;
};
Or, without the typedef, that easily confuses a beginner:
struct node; /* forward declaration (not strictly necessary in this little example) */
struct node *start;
struct node *current;
struct node {
int value;
struct node *next;
};
What you're doing in the second case is not a forward declaration. It's attempting to use a type (node) without defining it.
The first case doesn't quite work either. It gives the following warning:
warning: useless storage class specifier in empty declaration
That is because you're not assigning a type alias for struct node. You'd have to do it like this:
typedef struct node{
int value;
ptr next;
} node;
Now, you can use node in place of struct node.
I am studying code examples from my professor in order to become better acquainted with linked data structures.
In our linked-list.c example the professor defines a type Node as follows:
typedef struct node {
int data;
struct node *next;
} Node;
What's the point of the lower case node? I was under the impression that you could just write, for example:
typedef struct {
int data;
struct node *next;
} Node;
and then use Node as its own type. Does it have something to do with the fact that if you don't include a lower case node then when the compiler is evaluating the code it will not be able to understand what is meant by "struct node *next"?
Take a look at this declaration:
struct node {
int data;
struct node *next;
};
typedef struct node Node;
This can be combined into a single statement (simplifying a declaration):
typedef struct node {
int data;
struct node *next;
} Node;
Does it have something to do with the fact that if you don't include a lower case node then when the compiler is evaluating the code it will not be able to understand what is meant by "struct node *next"?
Yes.
The node in struct node is the tag of the struct type. If you give the struct a tag, you can refer to that type from the moment on the tag is complete, so in
typedef struct node {
int data;
struct node *next;
} Node;
the struct node *next; declares a member next that is a pointer to the struct type being defined. The typedef name Node is not available before the ; ending the definition is reached.
If you omit the tag, you cannot refer to the type being defined in any way before the typedef is complete, so in
typedef struct {
int data;
struct node *next;
} Node;
the line struct node *next; declares a new, unrelated, incomplete struct type with the tag node that next points to.
That's valid, but nothing about struct node is known (unless it is defined somewhere else), so you can't use the next pointer without casting it to a pointer to a complete type everywhere (not quite everywhere, Node foo; foo.next = malloc(12); etc. would still work).
He is defining a temporary name for the node because he is using a well know technique to avoid writing struct node on the declaration of each struct object.
If he would just do:
struct node {
int data;
struct node *next;
};
you would have had to use:
struct node* node;
to declare a new node. And to avoid that you would have to define later:
typedef struct node Node;
in order to be able to declare objects like the following:
Node* node;
In the end:
typedef struct node {
int data;
struct node *next;
} Node;
Is just a shortcut for struct node { ... }; in addition to typedef struct node Node;.
Here struct node is a type like int
and Hence
struct node {
int data;
struct node *next;
}NodeVar;
means you are declaring a single variable Node of struct node.
like int intVar;
typedef is to make your code understandable.
so that when you use
typedef struct node Node;
you can use the same declaration as
Node NodeVar;
Consider this code:
#include <stdio.h>
typedef struct {
int data;
struct node *next;
} Node;
int main()
{
Node a, b = {10, NULL};
a.next = &b;
printf("%d\n", a.next->data);
}
This won't compile. The compiler has no idea what a struct node is, other than it exists. So you might change the definition in the struct to Node *next;. The typedef isn't in scope before it's declared, so it still won't compile. The simple answer is to do as he said, use the node tag after struct, and it works fine.
The lower case 'node' is a structure type... i.e. a struct node { stuff } is a node structure containing stuff.
On the other hand, the upper case "Node" is a completely new data type which refers to a 'struct node'
Generally (though in C++ I think you can), you cannot pass around a "node" in a C program... for example as an argument to a function. Rather, you would have to pass a 'struct node' as your argument...
// this will throw a syntax error because "node" is not a data type,
// it's a structure type.
void myFunc( node* arg );
// while this will not because we're telling the compiler we're
// passing a struct of node
void myFunc( struct node* arg );
// On the other hand, you *can* use the typedef shorthand to declare
// passing a pointer to a custom data type that has been defined
// as 'struct node'
void myFunc( Node* arg );