1

i'm kinda new with C, so this question may sound too easy.

I tried to run this simple program, but got segmentation fault:

struct list {
    int data;
    struct list* next;
};

void makeList(struct list* list1) {
    list1 = (struct list*) malloc(sizeof(struct list));
    list1->next = NULL;
}

int main(int argc, char ** argv) {
    struct list * list1;
    makeList(list1);
    list1->data = 5;
    printf("data: %d\n", list1->data);

    return 0;
}

I know that the problem is list1->data = 5 in the main, but why?

The way i see it, the function makeList gets a pointer of struct list and allocates storage for it. And that's what i did, didn't i? i passed list1 by pointer. Why is it acting like list1 is not initiallized or something? Why doesn't it work?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
ryden
  • 189
  • 6
  • 1
    `list1` is actually uninitialized in `main()`. `makelist()` assigns only a local pointer. – Fred Larson Jan 26 '22 at 15:09
  • 1
    `list1` is passed by *value* to `makeList`, and whatever you assigned to it inside the function is not visible outside. – Eugene Sh. Jan 26 '22 at 15:09
  • by value? But ```list1``` in ```main()``` is a pointer, doesn't it? It has this ```*``` thing. How would i fix it? How do i pass it by reference/pointer? – ryden Jan 26 '22 at 15:17
  • 1
    Yes, but it's the pointer you're trying to change, not the item being pointed to, and the pointer is being passed by value. So you could use a double pointer, but in this case I think I prefer Vlad's solution of returning the pointer value. – Fred Larson Jan 26 '22 at 15:19
  • There's nothing special about pointers. If you do `int i=4; add5(int i) { i += 5; } printf("i==%d\n", i);`, you're going to see `i==4`. That's because the _copy_ of `i` was modified in `add5`, and that copy dies/goes out of scope when `add5` returns. Same as what you're doing here, just with a pointer. For changes to persist outside of functions in C, you either need to return a value or pass a pointer to what you want to modify, then dereference and modify what it points to. – yano Jan 26 '22 at 15:46

1 Answers1

2

In this declaration

struct list * list1;

there is declared a pointer that is uninitialized and hence has an indeterminate value.

In this call of the function makeList

makeList(list1);

there is passed a copy of the value of the pointer list1. So the function changes this copy of the value not the original pointer. The original pointer declared in main stays unchenged.

You could declare and define the function for example the following way

struct list * makeList( void ) 
{
    struct list *list = malloc( sizeof( struct list ) );
    if ( list != NULL ) list->next = NULL;

    return list;
}

And in main the function is called like

list1 = makeList();

Another approach is to pass the pointer declared in main to the function by reference. In C passing by reference means passing an object indirectly through a pointer to it. Dereferencing the pointer you can get an access to the original object.

For example

void makeList( struct list **list ) 
{
    *list = malloc( sizeof( struct list ) );
    if ( *list != NULL ) ( *list )->next = NULL;
}

and the function is called like

makeList( &list1 );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335