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