I have a simple question in understanding the pointers and struct definitions in the linked list code.
1)
typedef struct node
{
struct node* next;
int val;
}node;
here if I use two "node" when i initialize node *head; which node I am referring to?
2) Here I use an int val in the struct. If I use a void* instead of int is there any thing thats going to change ?
3)Also if I pass to a function
reverse(node* head)
{
node* temp = head; or node* temp = *head;
//what is the difference between the two
}
I am sorry if these are silly question I am new to c language.
Thanks & Regards,
Brett
<1>
in C you need to specify struct node for structs
struct node
{
...
} node;
the last 'node' is variable of type struct node
e.g.
node.val = 1;
and not a type.
if you want to use 'node' as a type you need to write
typedef struct node { .. } node;
<2>
if you use void* you will need a mechanism to handle what the pointers point to e.g. if void* points to an integer you need keep the integer either on the stack or the heap.
node n;
int value = 1;
n.val = &value; // pointing to a single integer on stack
int values[]={1,2,3};
n.val = values; // pointing to an array of integers on stack
void* ptr = malloc(sizeof(int));
n.val = ptr; // pointing to a single (uninit) integer allocated on heap
int* ptrval = (int*)ptr; // setting an int ptr to the same memory loc.
*ptrval = value; // ptrval now points to same as n.val does
<3>
reverse(node* head)
head is a pointer to your list, *head is the content of what the pointer points to (first node below)
head->[node next]->[node next]->[node
next]
EDIT: rephrased and edited.
EDITx2: apparently the question got edited and a typedef was added so the question was altered.
*head is the dereference of the pointer : ie the actual place in memory that is pointed to by the pointer head...
Think of head as a coat hanger and *head as the coat itself, if that helps.
ie:
struct * coat c; //this is a coat hanger, not a coat
....
struct coat k = *c;//this is the coat itself, not a coat hanger
For #1:
In C, struct's have a separate name space. So if you wrote:
struct foo { ... };
You then have to use struct foo to reference the type. If you tried just foo after the above definition, the compiler would give an error as it doesn't know anything about that unqualified name.
A typedef gives a type an alternate name. A typedef name does not need to be qualified, so once you do:
typedef struct foo foo;
You can now use an unqualified foo to reference the type. Since it's just an alternate name, you can now use struct foo and foo interchangeably.
For #2.
It's possible that if you changed val to a void * it could change the size of the entire structure. Whether that makes a difference will depend on how you've written the rest of your code.
Related
// Linked list implementation in C
#include <stdio.h>
#include <stdlib.h>
// Creating a node
struct node {
int value;
struct node *next; //What is this, what are we doing here?
};
// print the linked list value
void printLinkedlist(struct node *p) {
while (p != NULL) {
printf("%d ", p->value);
p = p->next;
}
}
int main() {
// Initialize nodes
struct node *head;
struct node *one = NULL;
struct node *two = NULL;
struct node *three = NULL;
// Allocate memory
one = malloc(sizeof(struct node));
two = malloc(sizeof(struct node));
three = malloc(sizeof(struct node));
// Assign value values
one->value = 1;
two->value = 2;
three->value = 3;
// Connect nodes
one->next = two;
two->next = three;
three->next = NULL;
// printing node-value
head = one;
printLinkedlist(head);
}
I want to ask what are we doing here with this line of code?
it's in the creating a node part of the code (top).
struct node *next;
Are we assigning a pointer type struct variable for the sturct node but its inside of the same struct, assigning a variable named *next inside the same struct? But that isn't allowed, right?
we can either declare the variable out side the } and between ; or in the main()
function part of the code only, Isn't it?
Like
main()
{
struct node *next;
}
Again, then I came across a post mentioning it as a pointer to the structure itself, can anyone explaine how can we do this inside the same struct?
The next member points to another instance of struct node. Graphically, we usually represent it like this:
+–––––––+––––––+ +–––––––+––––––+
| value | next |––––> | value | next |
+–––––––+––––––+ +–––––––+––––––+
A struct type cannot contain an instance of itself - we can’t create a type like
struct node {
int value;
struct node next;
};
for two reasons:
The type definition isn’t complete until the closing }, and you cannot create an instance of an incomplete type;
The type would require infinite storage (struct node contains a member next of type struct node which contains a member next of type struct node which contains a member next of type struct node...);
However, we can declare next as a pointer to struct node, since we can create pointers to incomplete types. The size and representation of a pointer is independent of the size and representation of the type it points to.
What it means
The line struct node *next; is read as "next is a pointer to another struct node".
This is just a recursive structure declaration (definition):
struct node {
int value;
struct node *next; //What is this, what are we doing here?
};
It says a node consist of two parts:
an integer value
a pointer to another node.
The wiki article on linked lists has a nice visualization showing how one node points to another (or to NULL to end the chain).
How does it work?
As you noted, the interesting part is how the declaration can include a reference back to itself. The compiler handles this in two steps:
It sizes the struct as consisting of an int and a pointer (they're all the same size regardless of what they are pointing to).
Later it type checks the assignment and generates the appropriate assembly. When you write one->value = 1;, it makes sure the 1 is an integer and generates code to move 1 to the integer slot. And when your write one->next = two;, it verified that two is a pointer to a node and generates code to move that pointer to the second slot for the struct node pointer.
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
I have a struct:
struct structname
{
structname** link;
int total;
}
I want to link structname1 to structname2. What I did was:
int *ptr = &structname2;
structname1 -> link = &ptr;
Then I tried to access the link for structname1 which is structname2:
structname *test = structname1 -> link;
Is this the correct way to do it? When I tried to print out, some unknown symbols printed. Can someone help me with this? Thanks.
You have to do in the below way.
struct structname structname1, structname2; //define two structures structname1 and structname2 of type structname.
struct structname * ptr; // ptr is a pointer to struct of type structname.
struct structname ** ptr2 // ptr2 is a double pointer to struct of type structname.
ptr = &structname2; // ptr points to structname2
ptr2 = &ptr; // ptr2 points to ptr and ptr points to structname2;
structname1.link = ptr2; // now link is a double pointer to structname2.
Let me correct if i'm wrong or missing
You have a couple of things wrong in your code. First, you got the type for ptr wrong: it should be struct structname ** instead of int *.
But if you're trying to do a linked list, you don't need the double indirection level at all. This is most likely what you want:
struct structname
{
struct structname *link;
int total;
}
With that, linking structname1 with structname2 is then as simple as (assuming structname1 and structname2 are of type struct structname):
struct structname *ptr = &structname2;
structname1.link = ptr;
If structname1 and structname2 are of type struct structname *, then you need this instead:
struct structname *ptr = structname2;
structname1->link = ptr;
You could also drop the intermediate variable ptr, it's not of much use here.
struct node {
struct node *next;
int cargo;
}
struct node *current, *last, *next;
unsigned char i;
current = (struct node*)(calloc(sizeof(struct node)));
for (last = current, unsigned char i = 5; i--;) {
next = (struct node*)(calloc(sizeof(struct node)));
next->cargo = i;
last->next = next;
}
The above code is a very easy linked list. Note that I changed a couple of things compared to your code. I create the objects using calloc, that means that the objects will be allocated on the heap instead of the stack. This also doesn't require you to have explicit names for every element, a.k.a. node in the linked list. It also means it won't be destroyed when you leve the scope of the names. Of course you will need to free all the nodes later, when you don't need the list anymore.
Then you don't need a pointer to a pointer in the node, a simple pointer is sufficient. In your main program you should also use an appropriate pointer. Even though, all pointers are the same size and can be cast into each other, you should - whenever possible - usde the right type.
Here I create another 5 nodes in a loop to demonstrate how 'flexible this approach is'.
If you want to do a circular linked list, that is quite easy as well. Simply append these line:
next->next = current;
struct node
{
int coef;
int exp;
struct node *link;
};
typedef struct node *NODE;
It defines NODE as a synonym for the type struct node *, so when you'll be declaring a variable of type NODE you'll be actually declaring a pointer to struct node.
Personally, I don't think that such declaration is a good idea: you're "hiding a pointer" (which is almost always a bad idea), and, moreover, you are not highlighting this fact in any way into the new name.
It makes NODE a typedef for a struct node *.
NODE becomes an alias for struct node*.
EDIT: Okay, for the comment (if I write my answer as comment, it would be too long and not formatted):
There's no different way to write this. Here, typedef is used just to create a synonym/alias for pointer to struct node.
An example for usage would be:
void f()
{
// some code
NODE p = NULL;
// do something with p
// for example use malloc and so on
// like: p = malloc( sizeof( struct node ) );
// and access like: p->coef = ..; p->expr = ..
// do something with p and free the memory later (if malloc is used)
}
is the same as
void f()
{
// some code
struct node* p = NULL;
// do something with p
}
Using NODE makes it just shorter (anyway, I wouldn't advise such typedef, as you're hiding, that it's a pointer, not a struct or other type, as mentioned in #Matteo Italia's answer).
The format, you're referring: "typedef struct{}type_name format" is something else. It's kind of a trick in C, to avoid writing struct keyword (as it's obligatory in C, and NOT in C++). So
typedef struct node
{
//..
} NODE;
would make NODE alias for struct node. So, the same example as above:
void f()
{
// some code
NODE p;
// do something with p
// note that now p is automatically allocated, it's real struct
// not a pointer. So you can access its members like:
// p.coef or p.expr, etc.
}
is the same as
void f()
{
// some code
struct node p;
// do something with p
}
NOTE that now, p is NOT a pointer, it's struct node.
simply tells you can create pointer of node type using only NODE every time instead of writting struct node * everytime
what does typedef struct node *NODE indicate?
UPPERCASE IS NO GOOD
Reserve ALL UPPERCASE identifiers for MACROS.
This is code for a linked list in the C programming language.
#include <stdio.h> /* For printf */
#include <stdlib.h> /* For malloc */
typedef struct node {
int data;
struct node *next; /* Pointer to next element in list */
} LLIST;
LLIST *list_add(LLIST **p, int i);
void list_remove(LLIST **p);
LLIST **list_search(LLIST **n, int i);
void list_print(LLIST *n);
The code is not completed, but I think it's enough for my question. Here at the end of struct node "LLIST" is used, and it's also used as a return type in the prototyping of the function list_add. What is going on?
That's a typedef. It's actually doing two things at once. First, it defines a structure:
struct node {
int data;
struct node *next;
}
And then does a typedef:
typedef struct node LLIST;
That means LLIST is a type, just like int or FILE or char, that is a shorthand for struct node, your linked-list node structure. It's not necessary - you could replace LLIST with struct node in all of those spots - but it makes it a bit easier to read, and helps hide the implementation from pesky end-users.
LLIST is just another type name for the struct that has been created. In general, the following format will create a type "NAME" that is a "struct x":
typedef struct x { ... } NAME;
C requires that you reference structs with a "struct" prefix, so it's common to introduce a typedef for less verbose mention.
That is, the declaration of your struct has two parts, and can be rewritten as such:
struct node {
int data;
struct node *next; /* pointer to next element in list */
};
typedef struct node LLIST;
So, LLIST is just another name for struct node (thanks Chris Lutz).
typedef creates a new "type" in your program, so the return value and types of parameters of those functions are just your struct. It is just shorthand for using struct node for the type.
If you were to create a new node, you could do it like this (using the type):
LLIST *node = malloc(sizeof(LLIST));
node->data = 4;
node->next = someOtherItem;
list_add(node, 1)
Also, with the function prototypes in your question, you don't really need the double pointers; since the data in your struct is just an int, you could do something like
LLIST *list_add(int data, int position);
then the list_add function would handle the allocation, copy the int into the struct and add it to the linked list.
Putting it in at a certain position is as simple as changing the next pointer in the node before it to the address of the newly allocated node, and the next pointer in the new node to point at the next one (the one the node before that one was originally pointing at).
Keep in mind that (given the rest of your function prototypes) you will have to keep track of pointers to every node you create in order to delete them all.
I'm not sure I understand how the search function will work. This whole thing could be implemented a lot better. You shouldn't have to provide the location of a node when you create it (what if you specify a higher number than there are nodes?), etc.
LLIST* is a pointer to a structure defined by the LLIST struct.
You should do
LLIST* myList = malloc(sizeof(LLIST)*number_of_elements);
to have some memory allocated for this list. Adding and removing items requires you to reallocate the memory using realloc. I've already written some piece of code for lists (made with arrays).
I might post the code as soon as I'm home, which is currently not the case.