Linkedlist в программировании на C

#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 из этих правил нет исключений.

  1. Каждый раз и только тогда, когда вы выполняете malloc , вы должны рисовать новое поле.
  2. Каждый раз и только при использовании free вы должны удалять (или просто пересекать его крестиком или чем-то еще) поле.
  3. Каждый раз, когда вы используете free , удаляйте все стрелки из этого поля.
  4. Каждый раз, когда вы присваиваете указатель на значение, нулевое или ненулевое, удаляйте старую стрелку, если она существует.
  5. Каждый раз и только тогда, когда вы присваиваете указатель ненулевому значению, рисуйте стрелку.

Примечание: Для обычного вызова 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 есть два типа, а не только целые числа?