Reputation: 1320
For the following linked list declaration,
#include <stdlib.h>
#include <stdio.h>
typedef struct list
{
int val;
struct list *next;
} list;
void destroy (list *l)
{
if (l)
{
destroy (l->next);
free (l);
}
}
why does the following main work
int main()
{
list *test;
list *ptr1, *ptr2;
int i;
test = malloc (sizeof (list));
test->val = 0;
ptr2 = test;
for (i = 1; i <= 10; i++)
{
ptr1 = (list *) malloc (sizeof (list));
ptr1->val = i;
ptr2->next = ptr1;
ptr2 = ptr1;
}
ptr1 = test;
while (ptr1)
{
printf ("%d\n", ptr1->val);
ptr1 = ptr1->next ;
}
destroy (test);
return 0;
}
while this one doesn't even create a list (it only makes one node)?
int main()
{
list *test;
list *ptr;
int i;
test = malloc (sizeof (list));
test->val = 0;
ptr = test->next;
for (i = 1; i <= 10; i++)
{
ptr = (list *) malloc (sizeof (list));
ptr->val = i;
ptr = ptr->next;
}
ptr = test;
while (ptr)
{
printf ("%d\n", ptr->val);
ptr = ptr->next ;
}
destroy (test);
return 0;
}
Don't they use the same logic?
Upvotes: 1
Views: 131
Reputation: 42165
The code
ptr = test->next;
for (i = 1; i <= 10; i++)
{
ptr = (list *) malloc (sizeof (list));
ptr->val = i;
ptr = ptr->next;
}
starts by taking a copy of test->next
but never assigns anything to test->next
itself. A list starting from test
therefore only has a single item. Worse, that item has an uninitialised next
pointer so code that tries to iterate over the list will almost certainly crash.
As hinted at in the other answers, this pattern is repeated for each newly allocated node.
In answer to your comment, the best way to make the second function work is to make it more like the first (working) version. I've renamed the variables in it to try to make it clearer
list *head;
list *next, *curr;
int i;
head = malloc (sizeof(*head));
head->val = 0;
curr= head;
for (i = 1; i <= 10; i++)
{
next = malloc (sizeof(*next));
next->val = i;
curr->next = next;
curr= next;
}
curr= head;
Upvotes: 3
Reputation: 6606
In the second main during
ptr = test->next;
you are trying to acces test->next withouth allocating memory for it.You can try changing your code as following to get second main working
test = malloc (sizeof (list));
test->val = 0;
test->next = (list *) malloc (sizeof (list));
ptr = test->next;
for (i = 1; i <= 10; i++)
{
ptr->val = i;
ptr->next = (list *) malloc (sizeof (list));
ptr = ptr->next;
}
Upvotes: 1
Reputation: 8116
It looks like in the first example, which works, ptr2
is holding the previously created node in the list, so that this can be rewritten
last_created_node = test;
for (i = 1; i <= 10; i++)
{
// create new node
new_node = (list *) malloc (sizeof (list));
new_node ->val = i;
// chain newly created node onto list so far
// make last created node point to new node
last_created_node->next = new_node ;
// last created node is now new node
last_created_node = new_node ;
}
// terminate the list
last_created_node->next = 0;
There is no equivalent of linking a new node onto the chain in the second code sample you give. Also there are problems with unitialised memory as others have commented. Would be good to add the termination condition as shown in the last line of my sample above.
Upvotes: 1