Значение структуры, передаваемой по значению, не изменяется

#c #pointers #struct #linked-list #pass-by-value

#c #указатели #структура #связанный список #передача по значению

Вопрос:

Я пытаюсь понять, как передать структуру по ссылке, чтобы создать связанный список. Метод, который я использую, аналогичен приведенному ниже примеру кода. Однако при выполнении этого кода *tester, объявленный в функции main, всегда остается нулевым. Является ли передача структуры функции AddNode() таким образом неуместной (компилятор не выдает никаких предупреждений)?

 struct test{
  int num;
  struct test *next;
};
void addNode (int num, struct test* tester);

int main (void){
  struct test *tester = null;
  addNode(1, tester);
}

void addNode(int num, struct test* tester){
  struct test *example = malloc(sizeof(struct test));
  example->num = num;
  if (tester == NULL){
    tester = example;
  } else{
    tester->next = example;
  }
}
  

Комментарии:

1. if (tester = NULL) … не кажется ли вам этот оператор странным?

2. К вашему сведению, C не имеет понятия о передаче по ссылке. Я понимаю, что в данном случае это проблема терминологии, но передача копии указателя не передается по ссылке.

3. @EtiennedeMartel Извините за это. Я исправил синтаксис в примере, но проблема сохраняется.

4. tester = example; должно вызывать ошибку компиляции. Вы должны исправить ошибки компиляции, прежде чем пытаться понять какой-либо вывод. И если это не ваш реальный код … скопируйте и вставьте в свой реальный код, иначе вы просто теряете время. null также является ошибкой.

Ответ №1:

В addNode функции указатель tester больше не указывает на местоположение, указанное tester in main . функция и измените свою функцию на

 void addNode(int num, struct test** tester){
    struct test *example = malloc(sizeof(struct test));
    if (NULL == example )
         exit(0);        // Not enough memory

    example->num = num;  
    if (NULL == *tester)
         *tester = example; 
    else
        (*tester)->next = example;
}  
  

Вызовите эту функцию из main as addNode(1, amp;tester); . Now *tester — это псевдоним для tester in main .

Комментарии:

1. Все равно не будет работать, поскольку он присваивает новое значение копии указателя в этой ветви. Ему нужно передать test**

2. @EdS. Каков наилучший способ обойти эту проблему?

3. «… передать test** «. Кроме того, ваше объявление example неверно.

4. @EdS. Будет ли это означать наличие void addNode(int num, struct test** tester) ? Если да, то как мне вызвать этот метод?

5. @mCode: я просто пошел дальше и опубликовал ответ, поскольку ни одна из них не затронула все проблемы с вашим кодом.

Ответ №2:

Во-первых, вы присваиваете NULL свой ввод. Это:

 if (tester = NULL)
  

должно быть

 if (tester == NULL)
  

Во-вторых, в той же ветке вы присваиваете новое значение tester . Однако все в C передается по значению (копия), поэтому ваша функция получает копию указателя. Следовательно, вы только изменяете локальную копию функции. Вам нужен другой уровень косвенности:

 #include <assert.h>

struct test{
  int num;
  struct test *next;
};

void addNode (int num, struct test* tester);

int main (void){
  struct test *tester = NULL;
  addNode(1, amp;tester);
}

void addNode(int num, struct test** tester){
  / * wrong, check next item */
  assert(tester != NULL);

  struct test example = malloc(sizeof(struct test));
  example->num = num;
  if (*tester == NULL){
    *tester = example;
  } else{
    (*tester)->next = example;
  }
}
  

Последнее, malloc возвращает a void* , который неявно может быть преобразован в указатель любого другого типа. Однако он не возвращает «экземпляр». Так что это неправильно:

 struct test example = malloc(sizeof(struct test));
  

и должно быть:

 struct test *example = malloc(sizeof *example);
  

Ответ №3:

Вы сохраняете указатель, возвращенный malloc как struct:

 struct test example = malloc(sizeof(struct test));
  

Возможно, вы хотели сохранить его как указатель на struct , чтобы example и tester иметь соответствующие типы:

 struct test* example = malloc(sizeof(struct test));
  

Тогда это будет иметь смысл:

 tester = example;