У меня возникли проблемы с пониманием того, как получить правильные значения, выдаваемые следующим кодом C++, при попытке решить его вручную.
#include <iostream>
using namespace std;
int f(int a, int & b,int *c){
a += 1;
b += 3;
*c += 4;
return a+b+(*c);
}
int main() {
int a = 3, b = 4,c = 5;
cout << "total: " << f(b,c,&a) << endl;
cout << "a= " << a << " b= " << b << " c= " << c << endl;
a = 3, b = 4,c = 5;
cout << "total: " << f(a,a,&a) << endl;
cout << "a= " << a << " b= " << b << " c= " << c << endl;
return 0;
}
Я знаю, что результат должен быть:
total: 20
a= 7 b= 4 c= 8
total: 24
a= 10 b= 4 c= 5
Но каждый раз, когда я пытаюсь решить этот код вручную (попытка записать шаги и задания на листе бумаги), я не могу получить правильную сумму или значения. Может ли кто-нибудь помочь мне понять, что происходит внутри функции с a, b и c (может быть, пошаговое объяснение?). Должно быть что-то, чего я не понимаю со ссылками/разыменованиями или указателями, что вызывает ошибки в моей логике. Даже
Например, если я попробую первый набор входных данных внутри функции, вот что я понимаю:
Затем я начинаю выполнять тело функции:
Окончательный результат: a = 7, b = 4 (не изменилось) и c = 8. Эти значения верны, но возвращаемая часть функции не работает с этими значениями:
a+b+(*c) должно быть 7+4+(7), но в результате получается 18, а правильный ответ 20.
Хуже всего то, что если я использую ту же логику во второй раз, когда функция вызывается, мои значения неверны, но моя сумма верна... Я потерян.
a = 3, b = 4,c = 5;
Это... подозрительно
@NicolBolas Я думаю, что это просто сбросить значения int обратно в исходное состояние во второй раз, когда функция вызывается, поскольку функция изменяет значения после выполнения.
Кстати, int &b = 5;
недействителен в С++. Вы можете/должны использовать отладчик вместо того, чтобы делать это вручную.
@JasonLiam Я не прошу кого-то отлаживать мой код, я прошу кого-нибудь объяснить результаты, так как я пытаюсь лучше понять, что происходит под капотом с этой функцией. Код не содержит ошибок, но моя логика есть.
@user21247827 user21247827 программисты обычно понимают поведение программы, которое их сбивает с толку, используя отладчик. Отладчик точно покажет вам, что происходит во время работы вашей программы.
Ну, мы не можем сказать вам, что не так с «шагами и заданиями на листе бумаги», которые вы записали, если вы не покажете, что именно, эти шаги и задания. Можете ли вы отредактировать свой вопрос и указать, что, по вашему мнению, происходит, и я уверен, что кто-то укажет точную ошибку. Если вы хотите, чтобы кто-то «объяснил» и помог вам «понять, что происходит», тогда вам нужно показать, во что, по вашему мнению, «происходит», чтобы другие могли помочь вам «понять».
@SamVarshavchik, вторая часть моего поста пытается показать, какие шаги я делаю, пытаясь найти решение. Я не уверен, что еще добавить в этот пост, чтобы лучше показать мои шаги.
@ user21247827: «Я не прошу кого-то отлаживать мой код, я прошу кого-нибудь объяснить результаты». Вот что такое «отладка»: это то, что вы делаете, когда ваш код дает результат, несовместимый с ожидаемым.
Я подозреваю, что ОП вызвал путаницу, используя одни и те же имена как в main()
, так и в аргументах функции. Например, вызов f(b,c,&a)
приводит к тому, что b
становится a
(в функции f()
), c
становится b
, а a
становится *c
.
@SamVarshavchik и Петр большое спасибо за ваши комментарии! Изменение имен переменных в функции на x, y, z значительно упростило понимание! Спасибо, что нашли время, чтобы сломать то, что я делал неправильно!
Окончательный результат: a = 7, b = 4 (не изменилось) и c = 8. Эти значения верны, но возвращаемая часть функции не работать с этими значениями:
Что вас сбивает с толку, так это то, что a
, b
и c
в вашем main
не то же самое, что a
, b
и c
в f()
.
return a+b+(*c);
Использует то, что f()
знает как a
, b
и c
. Это часть f()
. Переменные f()
— это единственное, о чем этот оператор return
знает что-либо, и он вообще ничего не знает ни о каких переменных в main
. Итак, чтобы узнать, что это за переменные, вам просто нужно перечитать то, что вы написали сами:
a += 1 теперь дает мне a = 5;
b += 3 теперь дает мне c = 8, так как b является ссылкой
но это b
, вот оно, то самое b
, что и в выражении return
.
*c += 4 теперь принимает значение, хранящееся в &a, инициализированное как 3, и добавляет 4, так что новое значение a равно 7;
Но это c
в выражении. Так
return a+b+(*c);
вычисляет 5+8+7
или 20
, как вы заметили.
Второе выражение работает так же.
Вас сбивает с толку тот факт, что переменные f()
используют те же имена, что и переменные в main()
. Также не помогает то, что указатели и ссылки из одного ссылаются на переменные в другом.
Вам может быть полезно переименовать переменные в f()
:
int f(int x, int & y,int *z){
x += 1;
y += 3;
*z += 4;
return x+y+(*z);
}
Это должно быть логически эквивалентно исходной функции, но с меньшей путаницей.
Проще всего это сделать с картинками, поэтому я постараюсь сделать ASCII-арт, показывающий, что происходит.
Вот ситуация сразу после того, как первый вызов вошел в f:
main a:3 b:4 c:5
^ ^
| /---/
| /
f c:* b:* a:4
Здесь «main» и «f» имеют свои собственные «a», «b» и «c»; а «b» и «c» в «f» указывают/относятся к вещам в фрейме основного стека. Я изменил порядок c/b/a в 'f', чтобы не было пересекающихся линий.
После трех сложений в f мы имеем
main a:7 b:4 c:8
^ ^
| /---/
| /
f c:* b:* a:5
Во втором вызове f все выглядит так:
main a:3 b:4 c:5
^
|\--\
| \
f c:* b:* a:3
и после добавления:
main a:10 b:4 c:5
^
|\--\
| \
f c:* b:* a:4
Мы не можем отлаживать вашу программу за вас. Используйте отладчик. Что такое отладчик и как он может помочь мне в диагностике проблем?