I came across a stack tutorial in the C language and I can't seem to understand what the *Stack pointer is pointing towards nor the *next pointer.
I would just like to have a quick explanation on what these two pointers actually point to.
typedef struct StackElement
{
int value;
struct StackElement *next;
}StackElement, *Stack;
Neither points to anything in the example you've given. This code is just the declaration of the structure type itself. You could break the typedefs out into maybe simpler form:
struct StackElement
{
int value;
struct StackElement *next;
};
typedef struct StackElement StackElement;
typedef struct StackElement *Stack;
That is, there is a declaration of the structure itself, which contains a field next to be used by the implementation code of this stack. That field, when filled in, will point to another struct StackElement structure.
The typedef parts just make convenience names - StackElement can be used in place of struct StackElement, and Stack can be used instead of struct StackElement *.
Related
I need help with declaring some structures to use in my code. The idea is that I need to declare some structures that are included in each other and use typedef to have a good coding style.
I have tried to declare these:
typedef struct cell
{
T_Tree list_of_sons;
struct cell *next;
}ListCell, *T_List, **Adr_List;
typedef struct node
{
int value;
T_List list;
}Node, *T_Tree;
It doesn't work because the type "T_Tree" is not declared before, but I would like to find a way to declare them while keeping the type definitions shown above.
Never (except function pointers) hide pointers in the typedef-s. It makes code more error prone and hard to read (you don't know when you see the declaration if something is a pointer or not).
struct node;
typedef struct cell
{
struct node *list_of_sons;
struct cell *next;
}ListCell;
typedef struct node
{
int value;
ListCell *list;
}Node;
Insert typedef struct node *T_Tree; before the first declaration. Then remove T_tree from the last declaration.
That declares T_Tree to be a pointer to a struct node. You may declare a pointer to a struct even though the struct does not have a complete definition.
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;
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"?
I'm implementing a linked list in C. Here's a struct that I made, which represents the linked list:
typedef struct llist {
struct lnode* head; /* Head pointer either points to a node with data or NULL */
struct lnode* tail; /* Tail pointer either points to a node with data or NULL */
unsigned int size; /* Size of the linked list */
} list;
Isn't the "llist" basically useless. When a client uses this library and makes a new linked list, he would have the following declaration:
list myList;
So typing llist just before the opening brace is practically useless, right? The following code basically does the same job:
typedef struct {
struct lnode* head; /* Head pointer either points to a node with data or NULL */
struct lnode* tail; /* Tail pointer either points to a node with data or NULL */
unsigned int size; /* Size of the linked list */
} list;
You need to give a struct a name if you will reference it in its declaration.
typedef struct snode {
struct snode* next;
struct snode* prev;
int id;
} node;
But if you won't reference the struct inside it you dont need to give it a name.
EDIT
Notice that typedef is and struct are two different statements in C.
struct is for creating complex types:
struct snode {
struct snode* next;
struct snode* prev;
int id;
};
Which reads like make a structure called snode that stores two references to itself (next and prev) and an int (id).
And typedef is for making type aliases:
typedef struct snode node;
Which reads like make a type alias for struct snode called node.
Yes, you are correct. It is only a matter of habit or convention to explicitly name the struct in addition to the typedef.
Note that there is little to no cost either way, since llist is not a variable and does not take up memory. It is like the difference between naming a variable i or index - the compiled form is the same, but one may be more readable than the other.
It's useless in that particular case but, if you wanted a pointer to that struct within the struct itself, it would be needed.
That's because the struct is known at the opening brace while the typedef isn't known until the final semicolon (simplistic, but good enough here).
So you would need it for something like:
typedef struct sNode { // structure can be used now
int payload;
struct sNode *next; // cannot use typedef yet
} tNode; // typedef can be used now
You could turn this around: not the structure tag, but the whole typedef is superfluous.
struct snode {
struct snode* next;
struct snode* prev;
int id;
};
Now you can declare a pointer with:
struct snode *ptr;
You can even declare an array of them:
struct snode mynodes[10];
You'll have to type the struct keyword, but that won't hurt the compiler or the human reader (look at that syntax highlighting!).
You could even declare a pointer to an unknown type (at this moment of compilation) using an incomplete type:
struct xnode *xptr=NULL;
That will come in handy when you want to create an API to some library, where the actually implementtation of the library is not known to the caller:
struct gizmo *open_gizmo(char *path, int flags);
int fiddle_with_gizmo(struct gizmo *ptr, int opcode, ...);
Et cetera. A typedef would force the header file to "broadcast" all its internals to the caller, even if that is not needed.