#c #linked-list
#c #связанный список
Вопрос:
В настоящее время я изучаю C, и одним из моих практических занятий является создание связанного списка на C.
typedef struct deck
{
int index;
struct deck *next;
} decks;
Мой вопрос в том, почему я не могу создать новый связанный список следующим образом: (индекс, карточка после «=» определяется как переменные)
decks* head = malloc(sizeof(decks));
decks* ptr = head;
for(int i = 0; i < 10; i ) {
ptr -> index = i;
ptr = ptr -> next;
ptr = malloc(sizeof(decks));
}
Большое спасибо!
Комментарии:
1.Потому что
ptr->next
неинициализирован и, конечно, не указывает на существующий блок памяти. В противном случае вам также не понадобился бы первыйmalloc
.2. что насчет сейчас? @AnttiHaapala
3. итак, да, теперь у вас будет как минимум 11 объектов, причем 10 из них содержат число, и ни один из них не связан со следующим, а 9 объектов утекли. Существует один кратчайший правильный способ сделать это, затем несколько более длинных способов создать связанный список и множество неправильных способов создать связанный список и еще больше способов попытаться создать связанный список и потерпеть неудачу в этом … уже существуют десятки QA о том, как это сделать правильно …
4. @AnttiHaapala Почему они просочились? Поскольку я ввел переменную «head» и перемещаю только указатели
5. Пожалуйста, избегайте изменения вашего вопроса. Это создает движущуюся цель и делает все предыдущие комментарии и ответы бесполезными.
Ответ №1:
Подсказка по указателям отладки
Рисуйте картинки. Создайте поле для каждого экземпляра и стрелку от каждого ненулевого указателя. ВСЕГДА следуйте правилам, перечисленным ниже. Предполагается, что все управление памятью выполняется с помощью malloc
и free
из этих правил нет исключений.
- Каждый раз и только тогда, когда вы выполняете
malloc
, вы должны рисовать новое поле. - Каждый раз и только при использовании
free
вы должны удалять (или просто пересекать его крестиком или чем-то еще) поле. - Каждый раз, когда вы используете
free
, удаляйте все стрелки из этого поля. - Каждый раз, когда вы присваиваете указатель на значение, нулевое или ненулевое, удаляйте старую стрелку, если она существует.
- Каждый раз и только тогда, когда вы присваиваете указатель ненулевому значению, рисуйте стрелку.
Примечание: Для обычного вызова malloc
вы должны использовать оба правила 1, 4 и 5. Использование malloc
без учета возвращаемого указателя означает утечку памяти.
Примечание2: Важно! Вам не следует удалять стрелку В поле, которое вы освобождаете при использовании free
. Делайте это только тогда, когда вы специально присваиваете указателю значение null. Точно так же не удаляйте флажок, когда вы присваиваете указателю значение null.
Примечание 3: Важно!Если вы освободите поле, в правиле 3 говорится, что вы должны удалить все стрелки из этого поля. НЕ удаляйте никаких полей, на которые указывают стрелки.
Ваш вопрос
Рассмотрим это:
ptr = ptr -> next;
ptr = malloc(sizeof(decks));
Первая строка не имеет никакого эффекта вообще, так как вы немедленно переназначаете ptr
.
Вам нужно что-то вроде этого:
ptr -> next = malloc(sizeof(decks));
ptr = ptr -> next;
Другие замечания
Я бы рекомендовал использовать sizeof для переменной, а не для типа, вот так: ptr->next = malloc(sizeof *(ptr->next))
В целом это хорошая привычка. Возьмите этот код:
int *x;
x = malloc(sizeof(int));
Теперь подумайте, хотите ли вы изменить тип переменной x
. Вам нужно было бы изменить аргумент на sizeof
при КАЖДОМ вызове malloc
. Использование x = malloc(sizeof *x)
полностью устраняет эту проблему.
Комментарии:
1. Большое спасибо!
2. Однако, что я могу сделать, если в struct есть два типа, а не только целые числа?