Понимание процедуры в C++

У меня есть следующий код на C++:

#include <iostream>
using namespace std;

int x;

void p(int a, int &b) {
    cout << x << " " << a << " " << b << endl;
    if (a < b) {
        a = x+b;
    }
    else {
        --x;
        b += a;
        a = x/2;
        cout << x << " " << a << " " << b << endl;
        p(b-x, a);
    }
    cout << x << " " << a << " " << b << endl;
}

int main() {
    x = 17;
    p(42, x);
    cout << x << endl;
}

Вывод этого кода следующий, чего я не понимаю:

17 42 17
58 29 58
58 0 29
58 87 29
58 29 58
58

В частности, в mainx=17 присваивает глобальный параметр. Начинается расчет p(a=42,&b=17). Он печатает: x = 17 (global),a = 42 ,b = 17 (pointer). До сих пор хорошо!

Далее он переходит к if. if 42<17 не удовлетворяется и переходит к else, в котором x уменьшается на единицу так x=17-1=16. Не 58.

Что происходит? Может кто-нибудь объяснить?

Да, кто-нибудь может это объяснить: ваш отладчик может это объяснить. Именно для этого и нужен отладчик: он запускает вашу программу по одной строке и показывает, что происходит. Используя отладчик, вы можете выполнять эту программу шаг за шагом, проверять значения всех переменных на каждом этапе и точно видеть, что происходит. Умение эффективно использовать отладчик — необходимый навык для каждого разработчика C++. Что показывает вам ваш отладчик, когда вы запускаете эту программу?

Sam Varshavchik 07.10.2023 21:25

@SamVarshavchik Я не знаю, как использовать отладчик. Я новичок в c++. Как я могу использовать отладчик в XCODE?

Homer Jay Simpson 07.10.2023 21:27

Знаете ли вы, что такое ссылки и что такое рекурсия? Эта программа может показаться простой, поскольку в ней не так много строк, но на самом деле она довольно сложна.

Fiddling Bits 07.10.2023 21:27

Лично я не знаю XCode и не использую Mac, но первый результат по запросу «xcode debugger» в Google показал мне эту многообещающую статью.

nanofarad 07.10.2023 21:28

Если вы «новичок в C++», то вы, должно быть, изучаете C++ по хорошему учебнику. Какова тема главы в вашем учебнике по C++, из которой взята эта практическая задача?? Это действительно странный пример программы, который можно встретить во вводном курсе C++. Можете ли вы объяснить, как именно вы, изучая C++, столкнулись с такой бесполезной головоломкой по программированию, которая не имеет абсолютно никакой обучающей ценности с точки зрения преподавания основных фундаментальных концепций C++?

Sam Varshavchik 07.10.2023 21:33

Дело в том, что вы обрабатываете в памяти две ссылки на одно и то же значение: Одна: глобальная x Вторая: ссылка передается как b, но это b является адресом x. Таким образом, оба x, b обрабатывают один и тот же блок памяти (целое число)

Ripi2 07.10.2023 21:39

Я отредактировал код ОП, чтобы улучшить форматирование и сделать более понятным, что он делает.

selbie 07.10.2023 21:39

«итак x=17-1=16. Не 58.»: Вы правильно рассмотрели все до --x; включительно, но затем пропустили рассмотрение побочных эффектов b += a;.

user17732522 07.10.2023 21:40

@ user17732522, потому что b += a; идет после --x.

Homer Jay Simpson 07.10.2023 21:43

@HomerJaySimpson Да, но это происходит до того, как будет напечатана вторая строка вывода. Поэтому его побочные эффекты могут повлиять на результат. В этом случае линия оказывает побочный эффект на значение объекта x, поскольку b является ссылкой на x.

user17732522 07.10.2023 21:44

@user17732522 user17732522 понял. Большое спасибо.

Homer Jay Simpson 07.10.2023 21:46
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
5
11
141
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш параметр b является ссылкой (т. е. псевдонимом) на переменную int. В данном случае это относится к глобальной переменной x, поскольку именно ее передает main(). Итак, x и b — это отдельные имена для одного и того же блока памяти, содержащего значение int. Таким образом, все, что вы делаете с x, отражается на b и наоборот.

Когда ваш код переходит к else в первый раз, значение x (и, следовательно, b) равно 17. Вы уменьшаете x (и, следовательно, b) на 1, а затем увеличиваете b (и, следовательно, x) на a (42). Итак, вы на самом деле увеличиваете x на 41, поэтому x становится 58 (17-1+42=58).

Другие вопросы по теме