Как передаются данные в параметры функций и как избежать потери данных на пути

Рейтинг: 0Ответов: 0Опубликовано: 12.08.2023

Давно мучился с функцией, удаляющей элемент в односвязном списке подобного рода:

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'а - по одному до преобразования и по одному после).

то, что выводится. Как видно, through1 остался со старым значением

Я подозреваю, что здесь необходим volatile, но то ли я как-то неправильно его использую, то ли не решает это проблему. Volatile использовал на объявлении list - объекта головы структуры, а также пробовал на this в through1.

Ответы

Ответов пока нет.