Structure pointer behaving weirdly

92 Views Asked by At
#include <stdio.h>

struct stu {
    int roll;
    struct stu *next;
} stu1;

int main() {
    stu1.roll = 1;
    
    struct stu *head = &stu1; // Question about this line
    head->next = &stu1;

    printf("Address of Head : %p, Head->Next : %p, Head->Data : %d\n", 
           &head, head->next, head->roll);
    printf("\nAddress of stu : %p,Stu->Next : %p, Stu->Data : %d", 
           &stu1, stu1.next, stu1.roll);

    return 0;
}

So the line where I have declared the head pointer to structure, when I assign it as struct stu * head = &stu1; it just runs fine the whole program runs fine, but when I write struct stu * head; or struct stu * head = NULL; the program says segmentation fault.

I don't understand like what's the difference in them and ig when using Linked List, I would have to assign head as Head->next = headnode not as Head = &Headnode.

3

There are 3 best solutions below

2
Chris On

If you try to dereference a null pointer or uninitialized pointer, you get undefined behavior. A segmentation fault is one possible result of this.

If you write:

struct stu *head = NULL; 
head->next = &stu1;

Then head doesn't actually point to anything. Bear in mind that head->next is equivalent to (*head).next.

2
Erdal Küçük On

A segfault is an access violation error, it occurs if one tries to access a restricted area of memory.

Constructs like

//declaration without initialization
struct stu *head; //undefined

//declaration with initialization
struct stu *head = NULL; //points to NULL

cannot be dereferenced, every attempt like

head->next;

will result in a segfault or at least undefined behaviour.

On the other hand, if you point to a valid region of memory, like

struct stu *head = &stu1;

then

head->next;

will return the address stored in next (which could be uninitialized, point to NULL or a valid object, so be careful dereferencing that).


Could be off topic, but if you want to implement a (single) linked list, then a logical approach would be to have two separated types

e.g.

//item type
struct item {
    int data;          //data storage
    struct item *next; //pointer to next item
};

//list type
struct list {
    //unsigned int size; //number of items in list
    struct item *head;   //first item in list
    struct item *tail;   //last item in list
};

then

//define some items
struct item item1 = {1, NULL};
struct item item2 = {2, NULL};
//...

//start with an empty list
struct list lst = {/*0,*/ NULL, NULL};
//add item 1
lst.head = &item1; //first item points to item1
lst.tail = &item1; //last item points to item1
//++lst.size;      //increase list size
//add item2
lst.tail->next = &item2; //set next of current last item to item2
lst.tail = &item2;       //set item2 as last item
//++lst.size;            //increase list size
//...
5
Wyck On

When you declare:

struct stu *head;

...then head is a pointer. If you leave it uninitialized you will get undefined behaviour when you dereference it with head->next. If you initialize it to NULL then you will also get undefined behaviour because you are attempting to dereference a NULL pointer.

But if you properly initialize head to be a pointer to some valid struct stu then things will go as planned.

struct stu *head = &stu1; // this is legal
head->next = &stu1; // this is also legal

Be aware that the code above, as you wrote it, is legal, but sets up a closed cycle where stu1's next pointer points right back to stu1.