-1

I want this function to add a point to the beginning of the linked list:

void addPoint(Point *head, int x, int y, SDL_bool dir) {
    Point *p = malloc(sizeof *p);
    p->x = x;
    p->y = y;
    p->dir = dir;
    p->next = head;
    head = p;
}

The head is initialized earlier like so:

Point *down = NULL;

Afterwards I call the function like so:

addPoint(&down, x * grid_cell_width, (y - 1) * grid_cell_height, SDL_FALSE);

Unfortunately this does not work as After after the call the head is still NULL.

  • 1
    One of the *many* duplicates of this problem [can be found here](https://stackoverflow.com/questions/7271647/what-is-the-reason-for-using-a-double-pointer-when-adding-a-node-in-a-linked-lis). Another one [here](https://stackoverflow.com/questions/66252089/not-able-to-push-when-implementing-linked-list-in-c). Both discovered by simply putting `[c] linked list push head update fails`. There are *hundreds* of others you can review as well. – WhozCraig Jun 25 '22 at 17:17

3 Answers3

2

You are passing a pointer to head, meaning you are passing a copy of the address of head to function addPoint. In the line where you are changing the value of head you are actually modifying the local pointer. To change that, you need to pass a pointer to a pointer, like so:

void addPoint(Point **head, int x, int y, SDL_bool dir) {
    Point *p = malloc(sizeof(Point));
    p->x = x;
    p->y = y;
    p->dir = dir;
    p->next = head;
    *head = p;
}
Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50
0

Try something like:

void addPoint(Point **head, int x, int y, SDL_bool dir) {
    Point* p = malloc(sizeof(p));
    p->x = x;
    p->y = y;
    p->dir = dir;
    p->next = head;
    *head = p;
}

In C there is no pass-by-reference mechanism per se, you just pass pointers to arguments instead (in this case, a pointer to a pointer). But those pointers are still just values, so a change to them is not visible outside of the function. What will be visible is a change to the value that the pointer points to. That's why you need to assign your p pointer to the location that the pointer head points to, hence you need to dereference it with (*) operator first.

Meeso
  • 36
  • 4
  • 2
    The assignment-from `malloc` here is completely wrong, and that alone is an indication something went off the rails. `Point p = malloc(sizeof(p));` shouldn't even compile. (invalid conversion from `void*` to `Point`). – WhozCraig Jun 25 '22 at 17:15
  • @WhozCraig As far as I am aware, that is only true for C++, https://stackoverflow.com/questions/1736833/void-pointers-difference-between-c-and-c . I agree casting it makes it more intentional(which In my opinion is better), but I do not believe it is inherently wrong in this particular context. – Dmytro Jun 25 '22 at 18:29
  • 1
    The code now, post change is *almost* correct. Your `sizeof` is still wrong; that's the size of a *pointer*, not the size of a `Point`. My prior comment is/was based on your initial post, and was accurate to that content. – WhozCraig Jun 25 '22 at 20:41
0

You got this part right:

addPoint(&down,...);

but the type of the expression &down is Point **, not Point *, so you need to change the definition of addPoint to

void addPoint(Point **head, int x, int y, SDL_bool dir) {
    ...
    p->next = *head;
    *head = p;
}

With this code, you have the following relationships:

 head == &down // Point ** == Point **
*head ==  down // Point * == Point *

So in the addPoint function, writing to *head is the same as writing to down.

John Bode
  • 119,563
  • 19
  • 122
  • 198