Как передаются данные в параметры функций и как избежать потери данных на пути
Давно мучился с функцией, удаляющей элемент в односвязном списке подобного рода:
typedef struct List* plist;
typedef struct List {
int val;
plist next;
} List;
Обнаружил странную вещь, от которой руки опускаются. Вот функция и, собственно, тестовый main (этот код рабочий):
void delete(plist* this) {
plist tmp = (*this)->next;
free(*this);
*this = tmp;
}
int main() {
int val;
plist list = NULL;
for (val = 1; val < 6; val++) {
list = addpage(list, val); //создание элемента в конце списка, рекурсивная, с ней проблем нет
}
plist last = list; /*(не пишу всего, чтобы не загромождать)*/
while (last->next)
last = last->next;
delete(&list->next->next);
printlist(list); //рекурсивная, печатает список, пока не уткнётся в NULL
return 0;
}
Расширяя код, я увеличил путь аргумента ("list->n.->n."), добавив в него (в путь) ещё пару функций, после чего тот же delete стал выдавать другие значения - то он, освобождая память (забивая поле "value" мусором), сам элемент из списка не убирал, то (конкретно в том виде кода, что приведён ниже) зацикливал список. Вот код с расширенным путём аргумента:
void change(plist* this) {
plist tmp = (*this)->next;
free(*this);
*this = tmp;
}
void through2(plist this) {
change(&this);
}
void through1(plist this) {
through2(this);
}
int main() {
/***тот же код***/
through1(list->next->next);
printlist(list);
return 0;
}
Так вот вопрос: что ту происходит и как подобного можно избежать? Если у меня есть ошибки в коде - я буду рад и благодарен, если вы на них укажите. Функции addpage() и printlist() проверены мною и временем, потому не вижу смысла лишний раз вам глаза портить. Жду любой помощи - уже несколько месяцев бегаю вокруг списков, ломая голову.
p.s.: после пары часов решил сбросить для демонстрации кусочек скрина с маркированным кодом:
void change(plist* this) {
plist tmp = (*this)->next;
free(*this);
*this = tmp;
printf("\nchange: %p", *this);
}
void through2(plist this) {
printf("\n2: %p", this);
change(&this);
printf("\n2: %p", this);
}
void through1(plist this) {
printf("\n1: %p", this);
through2(this);
printf("\n1: %p", this);
}
(это всё те же, только с обеих сторон от передач стоят выводы адресов this'а - по одному до преобразования и по одному после).
Я подозреваю, что здесь необходим volatile, но то ли я как-то неправильно его использую, то ли не решает это проблему. Volatile использовал на объявлении list - объекта головы структуры, а также пробовал на this в through1.