Reputation: 306
I have this code and I try to create a singly-linked list. However everytime I add a new element at the front, my code fails to point the element at the front of the list to the old element.
#include <stdio.h>
#include <stdlib.h>
struct list {
struct node* head;
};
struct node {
int data;
struct node* next;
};
struct list* list_init(void) {
struct list *l;
l = malloc(sizeof(struct list));
if (l == NULL) {
return 1;
}
else {
l -> head = NULL;
return l;
}
}
struct node* new_node(int num) {
struct node *n;
n = malloc(sizeof(struct node));
if (n == NULL) {
return NULL;
}
else {
n -> data = num;
n -> next = NULL;
return n;
}
}
int list_add_front(struct list* l, struct node* n) {
if (l == NULL) {
return 1;
}
else {
if (l -> head == NULL) {
// Make sure that the list head points to this node.
l -> head = &n;
}
// Make list head point to new node;
// Make new node point to old head node;
else {
struct node* old_head = l -> head;
n->next = old_head;
l -> head = &n;
}
}
}
int main()
{
struct list* l = list_init();
struct node* nn = new_node(2);
printf("l address: %p \n", l);
printf("n address: %p \n", nn);
list_add_front(l, nn);
int* datapoint = (l->head)->data;
printf("List head data at first: %i, on address %p. \n\n", *datapoint, datapoint);
struct node* nn2 = new_node(12);
printf("l address: %p \n", l);
printf("nn2 address: %p \n", nn2);
list_add_front(l, nn2);
int* datapoint3 = (l->head) -> data;
printf("List head data is now: %i, on address %p. \n\n", *datapoint3, datapoint3);
struct node* nextnode = (l->head) -> next;
printf("it points to address %p, which is the list itself. why?? . \n\n", nextnode);
}
I do not know why. It goes wrong in list_add_front
I believe.
I do not understand how it links to the address of the list struct itself, since printing the pointer seems to give that away.
Here is the executable code online, for convienence maybe: https://onlinegdb.com/rk7_meISN
Thanks in advance all.
Upvotes: 0
Views: 63
Reputation: 33601
As dbush pointed out, you have a number of warnings that need to be fixed. Be sure to compile with -Wall
In particular, in list_add_front
, change all &n
to n
. This should fix the problem. The compiler would/should flag this.
With &n
this is a pointer to a pointer of struct node
and not a pointer to struct node
[which is what you want]. Using &n
points to the address of n
, which is on the program stack and not what n
points to.
Here is an annotated and fixed version. It uses:
#if 0
// original code ..
#else
// fixed code ...
#endif
#include <stdio.h>
#include <stdlib.h>
struct list {
struct node *head;
};
struct node {
int data;
struct node *next;
};
struct list *
list_init(void)
{
struct list *l;
l = malloc(sizeof(struct list));
if (l == NULL) {
#if 0
return 1;
#else
return l;
#endif
}
else {
l->head = NULL;
return l;
}
}
struct node *
new_node(int num)
{
struct node *n;
n = malloc(sizeof(struct node));
if (n == NULL) {
return NULL;
}
else {
n->data = num;
n->next = NULL;
return n;
}
}
int
list_add_front(struct list *l, struct node *n)
{
if (l == NULL) {
return 1;
}
else {
if (l->head == NULL) {
// Make sure that the list head points to this node.
#if 0
l->head = &n;
#else
l->head = n;
#endif
}
// Make list head point to new node;
// Make new node point to old head node;
else {
struct node *old_head = l->head;
n->next = old_head;
#if 0
l->head = &n;
#else
l->head = n;
#endif
}
}
}
int
main()
{
struct list *l = list_init();
struct node *nn = new_node(2);
printf("l address: %p \n", l);
printf("n address: %p \n", nn);
list_add_front(l, nn);
#if 0
int *datapoint = (l->head)->data;
#else
int *datapoint = &l->head->data;
#endif
printf("List head data at first: %i, on address %p. \n\n",
*datapoint, datapoint);
struct node *nn2 = new_node(12);
printf("l address: %p \n", l);
printf("nn2 address: %p \n", nn2);
list_add_front(l, nn2);
#if 0
int *datapoint3 = (l->head)->data;
#else
int *datapoint3 = &l->head->data;
#endif
printf("List head data is now: %i, on address %p. \n\n",
*datapoint3, datapoint3);
#if 0
struct node *nextnode = (l->head)->next;
#else
struct node *nextnode = l->head->next;
#endif
printf("it points to address %p, which is the list itself. why?? . \n\n",
nextnode);
#if 1
return 0;
#endif
}
Upvotes: 2