Что происходит с временным указателем, выделенным стеком, при использовании в качестве возвращаемого значения?

#c #recursion #memory-management #singly-linked-list

#c #рекурсия #управление памятью #односвязный список

Вопрос:

Я задаю несколько основных вопросов по leetcode. Здесь я пытаюсь поменять местами пары односвязного списка, используя рекурсию. Приведенный ниже код проходит тесты, но какой-то момент ускользает от меня. new_head является указателем, созданным в стеке. Я понимаю, это означает, что как только функция возвращает результат, она очищается и потенциально может указывать на мусор. Правильно ли предполагать, что здесь это работает «случайно» и не является правильным способом сделать это или мое понимание неверно?

 /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     struct ListNode *next;
     * };
     */
    
        struct ListNode* swapPairs(struct ListNode* head){
            
        if (head == NULL || head->next == NULL) {
            return head;
        }    
            
            struct ListNode* new_head;
        
            new_head = head->next;       
            head->next = swapPairs(head->next->next);
            new_head->next = head;
          
            return new_head;
        
                        
        }
 

Еще один вопрос, связанный с приведенным выше кодом:

если я изменяю порядок назначений, я получаю переполнение стека, но я не могу понять причину, почему

         new_head = head->next;
        new_head->next = head;       
        head->next = swapPairs(head->next->next);
 

Ничто из того, что затронуто в этой строке new_head->next = head; , не влияет на то, что происходит внутри рекурсии no (ну, должно быть, но я это пропустил)?

Комментарии:

1. Если вы обнаружите, что набираете «Еще один вопрос», пожалуйста, остановитесь и подумайте о создании отдельного вопроса. В противном случае вы рискуете, что ваш вопрос будет помечен как не относящийся к теме из-за отсутствия внимания к одной проблеме.

2. в этом конкретном фрагменте кода есть утечка. new_head = head->next; переменная new_head больше нигде не используется. белый new_head->next перезаписан в new_head->next = head;

3. @milevyo: new_head возвращается вызывающему абоненту.

Ответ №1:

Первый вопрос

Return return new_head; не возвращает объект new_head вызывающему объекту. Он возвращает вызывающему абоненту текущее значение new_head . Это прекрасно.

Второй вопрос

С:

 new_head = head->next;       
head->next = swapPairs(head->next->next);
new_head->next = head;
 

в момент swapPairs вызова значение, переданное ему, head->next->next , является адресом некоторого узла, находящегося за пределами head->next списка.

С:

 new_head = head->next;
new_head->next = head;       
head->next = swapPairs(head->next->next);
 

во время swapPairs вызова ему передается значение, head->next->next head , потому new_head->next = head; что просто установлено head->next->next значение head .

Комментарии:

1. в этом конкретном фрагменте кода есть утечка. new_head = head->next; переменная new_head больше нигде не используется. белый new_head->next был перезаписан в new_head->next = head;