C - Указатель внутри фигурных скобок и двойных указателей - PullRequest
0 голосов
/ 24 февраля 2019

В настоящее время я изучаю некоторые вещи по базовым структурам данных и выполняю упражнения на C. В этой лаборатории рассматриваются двусвязные списки, и это основная функция, которую нужно добавить.Структура данных имеет смысл для меня, но я путаюсь с кодом.Почему здесь уместно иметь двойной указатель (**) на список, а не только один *.Кроме того, почему (* список) в скобках?

Я изучал указатели и изучал руководства.Я понимаю, что означают указатели, но я не уверен, почему здесь нужен двойной указатель.

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;
  }
}

, чтобы дать вам информацию о структуре, вот ее свойства:

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

Ответы [ 2 ]

0 голосов
/ 24 февраля 2019

Если вы хотите изменить входные параметры на функцию в C, вам нужны указатели.Так что если вы хотите изменить указатель, то вам нужен указатель на указатель.Без двойного указателя *list = (struct node *) malloc(sizeof(struct node)); было бы невозможно.

Кроме того, почему (* список) в скобках?

Поскольку *list->data будет интерпретироваться как *(list->data) otherwise.Если вы хотите избежать всех этих параметров, используйте временный указатель, такой как:

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

И не приводите malloc.Надлежащий способ написать *list = (struct node *) malloc(sizeof(struct node)); это *list = malloc(sizeof *list);

0 голосов
/ 24 февраля 2019

Почему здесь уместно иметь двойной указатель (**) на список, а не только один *

, потому что мы хотим изменить значение указателей и вернуть его взвонящий.Точно так же, как вы делаете:

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

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

Так же, как вы делаете

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.

В своей функции вы выделяете память для заголовка списка, если он пуст.Вам нужно вернуть этот указатель на вызывающего, чтобы вызывающий знал, с чего начинается заголовок списка.Итак, вы делаете:

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

Кроме того, почему (* list) в скобках?

Поскольку -> вычисляется сначала, а затем *.Это означает, что:

*a->b

анализируется как:

*(a->b)

т.е.:

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

, однако вы хотите сначала разыменовать указатель и получить доступ к базовой структуре,Т.е. у вас есть:

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`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...