Урок №13. Параметры и аргументы функций

  Юрий  | 

  |

  Обновл. 10 Янв 2023  | 

 245223

 ǀ   88 

На предыдущем уроке мы говорили о том, что функция может возвращать значение обратно в caller, используя оператор return. На этом уроке мы узнаем, что такое аргументы в функции и что такое параметры в функции.

Параметры и аргументы функций

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

Параметр функции — это переменная, которая используется в функции, и значение которой предоставляет caller (вызывающий объект). Параметры указываются при объявлении функции в круглых скобках. Если их много, то они перечисляются через запятую, например:

Параметры каждой функции действительны только внутри этой функции. Поэтому, если printValue() и add() имеют параметр с именем a, то это не означает, что произойдет конфликт имен. Эти параметры считаются независимыми и никак не взаимодействуют друг с другом.

Аргумент функции — это значение, которое передается из caller-а в функцию и которое указывается в скобках при вызове функции в caller-е:

Обратите внимание, аргументы тоже перечисляются через запятую. Количество аргументов должно совпадать с количеством параметров, иначе компилятор выдаст сообщение об ошибке.

Как работают параметры и аргументы функций?


При вызове функции, все её параметры создаются как локальные переменные, а значение каждого из аргументов копируется в соответствующий параметр (локальную переменную). Этот процесс называется передачей по значению. Например:

При вызове функции printValues() аргументы 8 и 9 копируются в параметры a и b. Параметру a присваивается значение 8, а параметру b — значение 9.

Результат:

8
9

Как работают параметры и возвращаемые значения функций?

Используя параметры и возвращаемые значения, мы можем создавать функции, которые будут принимать и обрабатывать данные, а затем возвращать результат обратно в caller.

Например, простая функция, которая принимает два целых числа и возвращает их сумму:

При вызове функции add(), параметру a присваивается значение 7, а параметру b — значение 8. Затем функция add() вычисляет их сумму и возвращает результат обратно в main(). И тогда уже результат выводится на экран.

Результат выполнения программы:

15

Еще примеры


Рассмотрим еще несколько вызовов функций:

Результат выполнения программы:

15
20
25
8
7
6

С первыми двумя вызовами всё понятно.

В третьем вызове аргументами являются выражения, которые сначала нужно обработать. 2 + 3 = 5 и результат 5 присваивается переменной a. 4 * 5 = 20 и результат 20 присваивается переменной b. Результатом выполнения функции add(5, 20) является значение 25.

Следующая пара относительно лёгкая для понимания:

Здесь уже a = x и b = x. Поскольку x = 4, то add(x, x) = add(4, 4). Результат — 8.

Теперь рассмотрим вызов посложнее:

При выполнении этого стейтмента процессор должен определить значения параметров a и b функции add(). С параметром a всё понятно — мы передаем значение 1 (a = 1). А вот чтобы определить значение параметра b, нам необходимо выполнить операцию умножения: multiply(2, 3), результат — 6. Затем add(1, 6) возвращает число 7, которое и выводится на экран.

Короче говоря:

add(1, multiply(2, 3)) => add(1, 6) => 7

Последний вызов может показаться немного сложным из-за того, что параметром функции add() является другой вызов add():

Но здесь всё аналогично вышеприведенному примеру. Перед тем, как процессор вычислит внешний вызов функции add(), он должен обработать внутренний вызов функции add(2, 3). add(2, 3) = 5. Затем процессор обрабатывает функцию add(1, 5), результатом которой является значение 6. Затем 6 передается в std::cout.

Короче говоря:

add(1, add(2, 3)) => add(1, 5) => 6

Тест

Задание №1: Что не так со следующим фрагментом кода?

Задание №2: Какие здесь есть две проблемы?

Задание №3: Какой результат выполнения следующей программы?

Задание №4: Напишите функцию doubleNumber(), которая принимает целое число в качестве параметра, удваивает его, а затем возвращает результат обратно в caller.

Задание №5: Напишите полноценную программу, которая принимает целое число от пользователя (используйте std::cin), удваивает его с помощью функции doubleNumber() из предыдущего задания, а затем выводит результат на экран.

Ответы


Чтобы просмотреть ответ, кликните на него мышкой.

Ответ №1

Функция multiply() имеет тип возврата void, что означает, что эта функция не возвращает значения. Но, так как она все равно пытается возвратить значение с помощью оператора return, мы получим ошибку от компилятора. Функция должна иметь тип возврата int.

Ответ №2

Проблема №1: main() передает один аргумент в multiply(), но multiply() имеет два параметра.

Проблема №2: multiply() вычисляет результат и присваивает его локальной переменной, которую не возвращает обратно в main(). А поскольку тип возврата функции multiply() — int, то мы получим ошибку (в некоторых компиляторах) или неожиданные результаты (в остальных компиляторах).

Ответ №3

Функция multiply() принимает следующие параметры: a = add(3, 4, 5) и b = 5. Сначала процессор обрабатывает a = add(3, 4, 5), т.е. 3 + 4 + 5 = 12. Затем уже выполняет операцию умножения, результатом которой является 60. Ответ: 60.

Ответ №4

Ответ №5

Примечание: У вас могут быть и другие решения заданий №4 и №5 — это ок. В программировании есть много случаев, когда одну задачу можно решить несколькими способами.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (1 079 оценок, среднее: 4,95 из 5)
Загрузка...

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

  1. Владимир:

    Вот так написал 4 программу, а потом увидел что это оказалось заданием пятой, спасибо.

  2. Gaba:

    Добрый день!
    пофантазировал и нафантазировал. Теперь не могу понять в почему не обрабатввется хотя в IDE никаких ошибок не показывает:

    1. Gaba:

      а все, разобрался. Зря объявил переменную. Отсюда вопрос: почему так нельзя делать, в чем загвоздка??? что бы понять на будущее. Спс

      1. Андрей:

        Если Вы про объявление переменной в теле функций, то они локальные. Область видимости в данном случае только в теле функции. Получается не совсем аргумент, который передали в функцию.

  3. Jenia:

    5 задание сделал вот так:

  4. Алексей:

    Добрый день, сделал 5 задание вот так:

    Меня интересует правильное ли это решение?

  5. Вардан:

    Отличнейший урок!
    хотелось бы добавить от себя что было бы неплохо добавить в уроке что манёвр add(1, multiply(2, 3)) то есть, поставить вместо аргумента, результат другой функции, работает только с функциями типа int, я сам напоролся на ошибку когда создавал рандомные программы, c функциями типа void этот манёвр не сработает.

    И ещё, вопрос который меня сильно интересует, в caller-е когда мы выводим функцию типа void, мы пишем саму функцию и перед ним не пишем std::cout <<, а пишем просто имя функции, круглые скобки, и аргументы внутри скобок, потом обязательно точка с запятой. Так вот, почему в этой строке с выводимым void функцией мы не можем написать std::endl?

    1. Fantasy:

      Это логично, потому-что тип возврата void не возвращает в caller значения. Если внимательно посмотришь то увидишь что у каждой ф-к в конце есть return a + b; или return a * b; .

  6. Михаил:

    Спасибо огромное за ваш труд! Материал воспринимается отлично! Всё очень наглядно, много примеров. Читаю литературу и паралельно ваши уроки. Наверное, для меня это самый лучший способ освоить язык. Поклон и уважение ;))

    1. Фото аватара Юрий:

      Пожалуйста)) Очень круто, что Равесли оказался Вам полезным))

  7. Mark:

    Автор этого сайта просто гений.
    Спасибо вам большое.

  8. Elena:

    Добрый день, благодарю за прекрасный материал. Я сделала 5е задание вот так:

    меня интересует: не будет ли в данном случае int main(int x) ошибкой?

    1. Евгений:

      Увы, Elena, использовать таким образом параметры функции main нельзя. Они зарезервированы для передачи аргументов из командной строки (если пока не понимаете, что это такое — не страшно, просто знайте, что main() без параметров — это сокращённая версия, которую можно использовать, когда не нужно передавать аргументы из командной строки). А вам нужно было просто объявить локальную переменную в функции main, то есть перед cin >> x; написать int x;

    2. Ekaterina:

      у меня очень похоже на вашу версию)

      1. Denis:

        Всё же лучше в функции doubleNumber не писать "лишнего": вывод на экран реализовать либо отдельной функцией, либо просто в main. Это связано с тем, что функция должна делать ровно то, что указано в её названии, она не должна выполнять избыточные функции.

  9. Анатолий:

    можно просто через запятую int add(int a, b) ?

    1. Steindvart:

      Нет, так как компилятор в данном случае не может вывести тип параметра b — необходимо явное указание типа. В отличии, например от случая со стейтментом.

      Например,

      Во многих реализациях компилятора вполне корректен с точки зрения синтаксиса. Но подобный стиль объявления и инициализации переменных не является хорошей практикой в большинстве сообществ.

  10. Александр:

    Как вы генерируете такое количество разнообразный нарисованных монстриков для аватарок? На чью не смотрю — у всех они разные… В чём секрет?

    1. Фото аватара Юрий:

      Это встроенная возможность WordPress. Он их сам генерирует рандомно)

  11. Арсен:

    Первым делом, Спасибо Огромное за Ваш курс!
    Я давно пытался освоить Язык С++ купил, не одну книгу, но так и не ладилось. А тут у Вас всё довольно ясно расписано.
    Задание №5 я выполнил немного по другому, не как в вашем ответе.
    Так как не вижу смысла забивать функцию main() лишним.

    1. Никита:

      Ну технически такого решения не должно быть. По 4-ому заданию такое усовершенствование функции излишне. Соответственно в 5-ом задании такая функция тоже неуместна. Но за энтузиазм респект)

  12. спиногрыз:

    чувак ты реально крут спасибо за то что ты потратил кучу времени на эти уроки ты нам реально помог

    1. Фото аватара Юрий:

      Пожалуйста))

  13. Катя:

    Спасибо за отличные уроки!
    И задам глупый вопрос. Пробую ввести все указанные Вами данные в примерах для практики. Вот прям четко по алгоритму,ни шагу в сторону. Идёт уйма ошибок в программе. Ладно,исправляю в силу возможностей. Не всегда получается.
    Вопрос: это я настолько тупая? Или так и должно быть?
    Может тогда мне чисто теорию почитать лучше.

    1. Фото аватара Юрий:

      Никаких ошибок не должно быть вообще, если вы всё делаете по урокам — это 100%. Если вы что-то меняете в коде, настройках своей IDE, используете онлайн-компиляторы, невнимательны или еще что-то — тогда возможны ошибки.

      Начинать изучение уроков, если у вас нет опыта, следует с урока №1 ничего не пропуская.

  14. Rock:

    Да простят меня те кто буду это читать)))

    1. Artem:

      Ах ты ж, хитрая жопа! ))

  15. Fray:

    Вопрос по второму заданию.
    Решил дописать в конце тела объявления функции multiply следующее: «return a * b;» и мне выдало следующую ошибку: «unused variable 'product'», что можно перевести как «неиспользованная переменная 'product'». Но какая разница какая переменная, ведь возвращаемое значение есть и это "return a * b".

    вот отредактированный код, чтобы лучше было видно:

    Однако если написать вместо "return a * b;" — "return product", то все сработает как надо.

    То есть, объявляя переменную в объявлении функции и присваивая ей определенное значение, нужно вернуть именно ее в caller? Потому что чтобы я не писал в return, мне выдавало ошибку «unused variable 'product'».

    Прошу прощения за свою невнимательность, если где то что то пропустил или мои вопросы звучат глупо, я еще в этом пытаюсь разобраться.
    Еще раз спасибо за предоставленные материалы.

    1. Александр:

      Проверил твой код, у меня все норм работает, ide — Visual Studio 2019 Community

    2. Никита:

      Скорее всего всё из-за настроек из предыдущих уроков. Если делали всё по урокам, то все Предупреждения(Warnings) распознаются как ошибки. В качестве Warning он ругается, дескать зачем объявили переменную, если не использовали вообще в функции — странно это, батенька. А так как Warning = ошибка при заданных по урокам настройках IDE, то он и не идёт дальше, сообщая об ошибке.
      Собственно ничего страшного нет и всё будет работать, но для этого автор и говорил о важности обращать внимания на предупреждения и подчищать хвосты.

    3. Spectre:

      По сути ты занял память переменной "product", которую не используешь, поэтому компилятор ругается, критической ошибки нет, просто ты нерационально используешь ресурсы.

    4. AHTOH:

      Вобще то unused в данном случае говорит о том что переменная product просто не используется и никак не влияет на компиляцию и выполнение программы.
      Компилятор просто обращает ваше внимание на то, что у вас есть неиспользуемые переменные и их смело можно "выкинуть" из кода.

  16. Asklepiy:

    Я параллельно вашим урокам начал читать другую литературу по С++. Где-то вычитал, что в идеале функция main() должна лишь вызывать другие функции, не принимая участия в вычислениях. Это верно?

    1. Руслан:

      Ну как, и да и нет. Если тебе удобно всё делать через функции — делай) Данный метод хорош при крупных проектах, где каждый программист пишет свою часть кода, а уже после подключают в главной функции.

  17. ХейЛонг:

    Читаю и вспоминаю любимую перегрузку функций. Вроде лёгкое явление, но препод постоянно акцентировал внимание на этом, видать больная тема для профессиональных разработчиков.

  18. Олександра:

    И почему вы раньше мне не попадались??! От многих заумных фраз других сайтов в состоянии "Взрыв мозга"

  19. Вадим:

    Сколько лучше читать уроков в день? Что бы не загружаться лишний раз и запомнить то что я прочитал)

  20. Daler:

    это 4

    вот 5

  21. Oleg:

    Спасибо вам огромное за бесплатные уроки! Мне очень нравится, всё понятно и в конце каждого урока тест, а это важно. Я до этого немного изучал Java, поэтому мне пока что всё просто. Вот моё решение №5:

  22. Олег:

  23. Владимир:

    Я в шоке, это лучшие уроки что я видел. Очень просто о том, что ранее не вмещалось в башку. Пока все понятно, и тесты реально закрепляют знания. Спасибо!

    1. Фото аватара Юрий:

      Пожалуйста 🙂

  24. Владимир:

    Спасибо за это замечательное объяснение, подобного нигде не встретил,замечательно!

    1. Фото аватара Юрий:

      Пожалуйста)

  25. diflikator:

    Вариант выполнения задания №2.

  26. Владимир:

    Здравствуйте, я может что то не так делаю, но VS 19 не работает если имя тела программы какое то кроме как int main. int doubleNumber() вот так уже не работает только main? в чем может быть проблема?

    1. Владислав:

      В предыдущих уроках это объяснялось, кажется. Функция main — это точка входа в программу. С нее и начинается выполнение программы. Функцию doubleNumber вы объявляете и описываете отдельно, а затем вызываете ее в внутри функции main.

  27. Aleksandr:

    Я все усложнил в 1000 раз, оказывается можно было намного проще код написать. Все верно получилось, но написал вот так:

    1. Sergey:

  28. Дмитрий:

    Чувак спасибо :))
    {
    благодарочка
    }

    1. Фото аватара Юрий:

      {
      Пожалуйста 😉
      }

  29. steyrin:

    Выдает ошибка "doubleNumber: функция не принимает 0 аргументов"

    1. Sergey:

      Как в поговорке a и b сидели на трубе)))

  30. Михалыч:

    альтернатива для пятого задания

    1. Innor:

      В задании было сказано: "Напишите функцию doubleNumber()". А вы её написали? Это задание ведь на проверку усвоения урока "Параметры и аргументы функции". Но согласен: путей решения задачи несколько.

    2. Vladimir Dal':

      Точно также решил

  31. Алексей:

    Немного другим путем пошел сразу после прочтения "В программировании есть много случаев, когда одну задачу можно решить несколькими способами."

    Подумал, так же и есть, а если…

  32. Steve Dekart:

    Я уже дошёл до этой темы и боюсь забыть прошлые темы. Боюсь что на 200 теме буду не помнить какую-нибудь там 30 тему

    1. Владислав:

      Без практики в реальных проектах забудешь все 100 тем. Забывать это нормально. Практикующему программисту приходится переодически заглядывать в справочные материалы, что-бы что-то вспомнить.

  33. Данис:

    А можете ли объяснить , я прост не понимаю почему в 3 задание в функции multiply b=5?

  34. олег:

    А такой вариант плох тем что одна функция выполняет 3 действия?
    И еще вопрос, почему code::blocks спокойно выводит в консоль русские буквы без добавления set_locale?

  35. yrneero:

    Один из лучших сайтов где можно выучить C++. Понятно все до мелочей, автору респект!!! Было бы неплохо добавить к примеру видео-уроки)). Еще раз спасибо за ваши старания

    1. Фото аватара Юрий:

      Пожалуйста 🙂

  36. Eugen:

    Добрый день.

    Хотелось бы добавить в данный урок более четкое разграничение функций с параметрами и без. Так как я считаю это важным. Делая задания по данному уроку решил немножко усложнить и столкнулся с проблемой понимания работы функции. То есть функция с параметрами требует аргумента, а функция без параметров нет. Но моя программа не работала… Регулярными ударами головой о проблему решил ее. Было интересно. Посему предлагаю рассмотреть данный вопрос.

    И конечно мой код:

  37. Илья:

    Вот тебе,админ, для примера альтернативная программа,ты в ответе предлагал вводить число в консоль,используя функцию main(),я написал альтернативную,где ввод происходит через функцию doubleNumber(),есть ли у такого способа минусы перед твоим,и если да,то какие???Код скомпиллировался,работает как надо.

    1. Илья:

      P.S:
      В таком решении ,когда мы в фукции main вызываем функцию doubleNumber(),её аргументом можно прописать произвольное число при этом считать умножаться будет то число,которое мы пропишем в консоли,а не аргумент.Кстати с аргументом "а" в функции doubleNumber код не компиллируется.

    2. Фото аватара Юрий:

      Вот беру и смотрю.

      Правило хорошего программирования: одна функция должна выполнять одну задачу. (об этом в следующих уроках рассказывается детальнее).

      У тебя doubleNumber выполняет две задачи: принимает число и умножает его. Для такой простенькой программы, как эта (это даже не программа — 13 строк кода всего лишь), можно использовать и такой, как у тебя вариант, и такой, как у меня, и другие, которые предлагали в комментариях. В более сложных программах оптимальным вариантом было бы сделать отдельную функцию для получения значения от пользователя и отдельную для умножения значения.

    3. Alexey:

      так будет правильнее

  38. Ray:

    У Вас, в примерах к уроку 13 указывается: using namespace std; и дальше везде все равно прописываются std: Корректно ли использование std: в добавок к using namespace std; ? Думаю, что они должны быть взаимоисключающими, я не прав ?

    1. Фото аватара Юрий:

      Вы правы. Спасибо за бдительность, исправил.

  39. master114:

    Сделал через функции, так сказать с заделом на правильность — http://www.onlinegdb.com/B1-Zzq3hM.

    1. Фото аватара Юрий:

      Всё правильно и согласно рекомендациям из этого туториала. Радует, что уловили суть и пишите программы с самого начала правильным образом.

  40. Parenochek1488:

    Я какой-то не правильный(

    1. Фото аватара Юрий:

      У вас тут несколько замечаний (по поводу using namespace std и объявления переменных в глобальной области видимости). Продолжайте читать уроки — постепенно всё узнаете и сами поймете, что у вас не так.

      1. Parenochek1488:

        Никак не могу запомнить, как работают параметры. Это решение единственное, которое пришло на ум. Но, как по мне, главное, что оно работает и введённое "a" умножается на два. Но урок я явно не усвоил, так что буду пробовать ещё. Спасибо за такой удобный сайт.

        1. Фото аватара Юрий:

          Пожалуйста. По поводу параметров есть не один урок, всё, что нужно — рассматривается.

  41. Семён:

    Спасибо ! Но по мне так лучше пока все поэтапно Но их плюс в том , что их можно повторять много раз .

  42. Александр:

    Для чего костыли с std:: ? Если можно реализовать все быстрее без него с помощью using namespace std;.

  43. Дарья:

    Все прекрасно! Спасибо Вам! Не думала, что когда-нибудь возьмусь за изучение и что моей головы на это хватит! Написала решение к 5 заданию и какого было мое удивление когда она заработала!))

    1. Фото аватара Юрий:

      Никогда не знаешь, пока не попробуешь 🙂

    2. максим:

      какого пачему твой код сильно похож на мой? рандом наверно

  44. Фото аватара Юрий:

    По началу так и делал. Но практика такая не прижилась, как видите 🙂

  45. Сергей:

    Нужно добавить на сайте систему (лайк,дизлайк) к коментариям.

    1. Фото аватара Юрий:

      Ну это уже в перспективе.

  46. Сергей:

    Один из лучших уроков легко и элементарно обьясняющий правило использования параметров в функции. Автору огромное спасибо, даже в книгах для новичков я не встречал раздела про параметры функции.

    1. Фото аватара Юрий:

      Спасибо, приятно 🙂

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *