简体   繁体   中英

C - Pointer inside curly brackets and double pointers

I am currently learning some stuff on basic data structures and completing the exercises in C. This lab is looking at doubly linked lists, and this is the basic function to append. The data structure makes sense to me but my confusion is with the code. Why is it appropriate here to have a double pointer (**) to the list rather than just the one *. Also why is (*list) in brackets?

I have been researching pointers and going through tutorials. I understand what the pointers mean but I'm not sure why a double pointer is appropriate here.

void append(struct node ** list, int num,)
{
  struct node *temp, *current = *list;
  if(*list == NULL)
  {
    *list = (struct node *) malloc(sizeof(struct node));
    (*list) -> prev = NULL;
    (*list) -> data = num;
    (*list) -> next = NULL;
  }
  else
  {
    while(current -> next != NULL)
    {
      current = current -> next;
    }

    temp = (struct node *) malloc(sizeof(struct node));
    temp -> data = num;
    temp -> next = NULL;
    temp -> prev = current;
    current -> next = temp;
  }
}

to give you information on the struct here are its properties:

struct node
{
  int data;
  struct node * prev;
  struct node * next;
};

Why is it appropriate here to have a double pointer (**) to the list rather than just the one *

Because we want to change the pointers value and return it to the caller. The same way you do:

void f(int *x) {
    *x = 5;
}

int y;
f(&y);
printf("%d\n", y); // will print 5

The same way you do

static int x_mem = 5;
void f(int **x) { 
    // x is a pointer to (pointer to int)
    *x = &x_mem;
}

int *y; // pointer to int
f(&y);
printf("%d %p %p\n", **y, (void*)y, (void*)&x_mem); // will print 5 and two same addresses of `x_mem` variable.

In your function you allocate the memory for the list head if it's empty. You need to return that pointer to the caller, so the caller knows where the list head starts. So you do:

*list = (struct node *) malloc(sizeof(struct node));

Also why is (*list) in brackets?

Because -> is evaluated first then * . That means that:

*a->b

is parsed as:

*(a->b)

ie:

struct A_s {
   int *m;
};
struct A_s *a = malloc(sizeof(struct A_s));
a->m = malloc(sizeof(int));  
*a->m = 5;

however you want to first dereference the pointer and access the underlying structure. Ie you have:

struct A_s a_mem;
struct A_s *a = &a_mem;
struct A_s **b = &a;
(*b)->m = malloc(sizeof(int)); // equivalent to `a->m` or `(*a).m` or `(**b).m`
*(*b)->m = 5; // equivalent to `*((*b)->m) = ` or `*(a->m) = ` or `*a->m`

If you want to change the input parameters to a function in C, you need pointers. So if you want to change a pointer, then you need a pointer to pointer. Without a double pointer, *list = (struct node *) malloc(sizeof(struct node)); would not be possible.

Also why is (*list) in brackets?

Because *list->data would be interpreted as *(list->data) otherwise . If you want to avoid all those parameters, use a temporary pointer like this:

void foo(int ** bar) {
    int * ptr = *bar;
    ptr->x = 42; // Equivalent to (*bar)->x=42;
}

And don't cast malloc. The appropriate way to write *list = (struct node *) malloc(sizeof(struct node)); is *list = malloc(sizeof *list);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM