Как передать значение в функцию c
Функция может принимать параметры. Параметры позволяет передать извне в функцию некоторые данные, настроить ее выполнение. Параметры перечисляются в скобках после имени функции имеют следующее определение:
тип имя_функции (тип параметр1, тип параметр2. тип параметрN)
Для каждого параметра сначала указывается тип, а затем название параметра. Через запятую определяется следующий параметр.
Например, мы хотим, чтобы функция выводила разные сообщения на консоль. Для этого определим функцию, которая в качестве параметра принимает массив символов:
#include // функция принимает массив символов void print_message(char message[]) < printf("%s\n", message); >int main(void)
Здесь функция print_message() принимает один параметр, который называется message и который имеет тип char[] . Параметр message еще называется формальным параметром
В функции main три раза вызываем функцию print_message, передавая ей разные значения — строки «Hello METANIT.COM!», «Hello World!» и «Hello work. «. Эти значения еще называют аргументами . Таким образом, на консоль будут выведены три строки:
Hello METANIT.COM! Hello World! Hello work.
Прототип функции print_message() выглядел бы следующим образом:
void print_message(char[]);
Полный пример с прототипом:
#include // прототип функции print_message void print_message(char[]); int main(void) < print_message("Hello METANIT.COM!"); >// определение функции print_message void print_message(char message[])
Если необходимо несколько параметров, то они перечисляются через запятую. Например, напишем функцию, которая вычисляет сумму двух чисел:
#include void sum(int x, int y) < printf("%d + %d = %d \n", x, y, x + y); >int main(void)
Функция sum() принимает два параметра типа int .
В методе main эта функция вызывается три раза, и каждый раз ей передается два разных аргумента для параметров x и y. Соответствие между аргументами и параметрами устанавливается по их расположению: первый аргумент передает значение для первого параметра, второй аргумент — для второго параметра и так далее. Консольный вывод программы:
1 + 2 = 3 4 + 5 = 9 6 + 2 = 8
Прототип функции sum выглядел бы следующим образом:
void sum(int, int);
Между передаваемыми в функцию аргументами и ее параметрами должно быть соответствие по типу. Если же типы не совпадают, то компилятор пытается автоматически выполнить преобразование типов.
Например, выше использовалась функция void sum(int, int) . Если мы передадим в sum значения другого типа, то компилятор будет пытаться привести их к типу int:
int main(void) < sum(1.4, 2.5); // передаем значения double sum(1.4f, 2.5f); // передаем значения float >
В обоих случаях фактически функция sum получить числа 1 и 2.
Процесс передачи параметров
При передаче параметров следует учитывать, то они передаются в функцию по значению . То есть функция не изменяет значения передаваемых аргументов. Рассмотрим следующий пример:
#include void increase(int x) < x = 2 * x; printf("Increase func: x = %d \n", x); >int main(void)
Функция increase через параметр получает число и увеличивает его в два раза.
В функции main вызываем функцию increase, передавая ей значение переменной a . И после того, как функция increase отработала и изменила значение своего параметра, проверяем значение переменной a .
И при выполнении мы увидим, что изменения аргументов в функции increase действуют только в рамках этой функции. Вне ее значение переменной a остается неизменным:
Increase func: x = 50 Main func: a = 25
Почему так происходит? При компиляции функции для ее параметров выделяются отдельные участки памяти. При этом для параметров типа float формируются в памяти объекты типа double , а для параметров типов char и short int — объекты типа int .
При вызове функции вычисляются значения аргументов, которые передаются на место параметров. И затем значения аргументов заносятся в участки памяти, отведенные для параметров. При этом значения типа float преобразуются в объекты типа double , а объекты типов char и short int — в объекты типа int .
Если в вызов функции передается переменная, то функция получает копию ее значения. Поэтому все манипуляции со значением параметра внутри функции никак не затронут оригинальную переменную.
После завершения работы функции память, выделенная для параметров, освобождается.
Константные параметры
Мы можем в функции изменить значение параметра:
void change(int n) < n = n * 2; // значение параметра изменяется printf("n = %d \n", n); >
Однако подобное поведение не всегда желательно. Нередко бывают ситуации, когда надо гарантировать, что параметр сохранит свое значение на протяжении всей работы функции. В этом случае можно объявить параметр как константный с помощью ключевого слова const :
void change(const int n) < //n = n * 2; // теперь параметр n нельзя изменить int m = n * 2; printf("n = %d \n", n); printf("m = %d \n", m); >
Если мы попробуем изменить значение константного параметра, то при компиляции мы столкнемся с ошибкой. Если же надо выполнять какие-то вычисления, то можно использовать дополнительную переменную.
Передача аргументов в функцию
Как уже отмечалось выше, при вызове функции в неё передаются не сами переменные, а только их значения. Т.е. функция, что бы она там ни делала, не может никак повлиять на значения переменных, которые в неё передаются. Такой способ передачи значений в функцию называется передачей аргументов по значению .
Рассмотрим пример. Допустим, мы хотим написать программу, которая меняет местами значения переменных. Кажется, всё просто.
#include void swap(int a, int b) < int temp; temp = a; a = b; b = temp; >int main(void)
Вроде бы всё должно работать, но нет. Запустите программу и убедитесь в этом. И дело, как видите, не в функции, функция работает правильно, и значения переменных a и b действительно меняются, но к нашим исходным переменным это не имеет никакого отношения, т.к. они в функцию не передавались, а передавались только их значения.
Это никуда не годится. Чтобы с этим справиться, необходимо использовать другой способ передачи аргументов в функцию – передачу аргументов по ссылке . Для этого нам придётся воспользоваться указателями. Надеюсь вы хорошо с ними разобрались на прошлом шаге.
Напомню, что указатель – это такая переменная, в которой хранится адрес в памяти. В зависимости от типа указателя по этому адресу хранится значение соответствующего типа. Перепишем нашу программу используя передачу аргумента по ссылке.
#include // функция swap принимает два указателя на целые числа // другими словами, два адреса в памяти компьютера, // в которых записаны целые числа void swap(int *a, int *b) < // a -- адрес первого числа // b -- адрес второго числа int temp; // *a -- разыменование указателя // *a позволяет обращаться к значению, хранящемуся по адресу a // выводим значения, хранящиеся по адресам a и b printf("a=%d b=%d\n",*a,*b); // переменной temp присваиваем значение, хранящееся по адресу a temp = *a; // в ячейку по адресу a записываем значение, хранящееся по адресу b *a = *b; // в ячейку по адресу b записываем значение из переменной temp *b = temp; printf("a=%d b=%d\n",*a,*b); >int main(void) < int x = 4, y = 9; printf("x=%d y=%d\n",x,y); // передаём адреса переменных x и y в фунцию swap swap(&x,&y); printf("x=%d y=%d\n",x,y); return 0; >
Программа снабжена подробными комментариями, но я ещё раз поясню, что происходит. В начале программы объявляются переменные x и y . Им присваиваются значения 4 и 9 соответственно. Адреса этих переменных передаются в функцию swap . Обращаю особое внимание. Передаются адреса переменных, а не их значения. Внутри функции, используя дополнительную переменную, значения по переданным адресам меняются местами. Функция swap заканчивает свою работу.
Передача массивов в функцию
Массивы, как и простые переменные, можно передавать в функцию, но есть ряд особенностей, с которыми нам следует познакомиться. Продемонстрирую их на примере. В следующей программе я написал две функции, которые выводят на экран переданный им массив.
#include void print_arr(int arr[], int n) < for (int k=0; kprintf("\n"); > void print_arr2(int arr[][5], int k, int n) < for (int i=0; iint main(void)< int q[5] = ; int q2[2][5] = < , >; print_arr(q,5); print_arr2(q2,2,5); return 0; >
Первый момент. Если в функцию предполагается передавать массив, то необходимо об этом предупредить компилятор. Для этого в заголовке функции при её описании необходимо рядом с именем переменной-массива указать пару квадратных скобок [] . Посмотрите на объявление функции print_arr : из него сразу понятно, что переменная arr будет массивом, т.к. рядом с её именем указаны [] .
void print_arr(int arr[], int n)
Второй момент. Когда мы передаём массив в функцию, то функция ничего не знает о размере этого массива. Поэтому необходимо дополнительно передавать размер массива в функцию отдельным параметром.
Третий нюанс. Если в функцию передаётся двумерный массив, то кроме двух пар квадратных скобочек [][] , во второй из них необходимо явно указать её размерность. В примере выше это 5 .
Четвертый нюанс. Массивы всегда передаются в функцию по ссылке. Это означает, что любые изменения массива внутри функции отразятся на исходном массиве.
Есть и другие способы передать массив в функцию, они связаны с передачей указателей на начало массива, но о них мы не будем упоминать в рамках данного курса.
Сохрани в закладки или поддержи проект.
Практика
Решите предложенные задачи:

Для удобства работы сразу переходите в полноэкранный режим
Дополнительные материалы
- пока нет
Как передать значение в функцию c
Аргументы, которые представляют переменные или константы, могут передаваться в функцию по значению (by value) и по ссылке (by reference).
При передаче аргументов по значению функция получает копию значения переменных и констант. Например:
#include void square(int); // прототип функции int main() < int n ; std::cout void square(int m) < m = m * m; // изменяем значение параметра std::cout Before square: n = 4 In square: m = 16 After square: n = 4
Почему так происходит? При компиляции функции для ее параметров выделяются отдельные участки памяти. При вызове функции вычисляются значения аргументов, которые передаются на место параметров. И затем значения аргументов заносятся в эти участки памяти. То есть функция манипулирует копиями значений объектов, а не самими объектами.
Передача параметров по ссылке
При передаче параметров по ссылке передается ссылка на объект, через которую мы можем манипулировать самим объектов, а не просто его значением. Так, перепишем предыдущий пример, используя передачу по ссылке:
#include void square(int&); // прототип функции int main() < int n ; std::cout void square(int& m) < m = m * m; // изменяем значение параметра std::cout по ссылке. Ссылочный параметр связывается непосредственно с объектом, поэтому через ссылку можно менять сам объект. То есть здесь при вызове функции параметрmв функцииsquareбудет представлять тот же объект, что и переменнаяnИ если мы скомпилируем и запустим программу, то результат будет иным:
Before square: n = 4 In square: m = 16 After square: n = 16Передача по ссылке позволяет возвратить из функции сразу несколько значений. Также передача параметров по ссылке является более эффективной при передаче очень больших объектов. Поскольку в этом случае не происходит копирования значений, а функция использует сам объект, а не его значение.
От передачи аргументов по ссылке следует отличать передачу ссылок в качестве аргументов:
#include void square(int); // прототип функции int main() < int n = 4; int &nRef = n; // ссылка на переменную n std::cout void square(int m) < m = m * m; // изменяем значение параметра std::cout Before square: n = 4 In square: m = 16 After square: n = 4Передача параметров по значению больше подходит для передачи в функцию небольших объектов, значения которых копируются в определенные участки памяти, которые потом использует функция.
Передача параметров по ссылке больше подходит для передачи в функцию больших объектов, в этом случае не нужно копировать все содержимое объекта в участок памяти, за счет чего увеличивается производительность программы.
Преобразования типов
Передача параметров по значению и по ссылке отличаются еще одним важным моментом. С++ может автоматически преобразовывать значения одних типов в другие, в том числе если подобные преобразования сопровождаются потерей точности (например, преобразование от типа double к типу int). Но при передаче параметров по ссылке неявные автоматические преобразования типов исключены. Так, рассмотрим пример:
#include void printVal(int); void printRef(int&); int main() < double value; printVal(value); // 3 printRef(value); // ! Ошибка > void printVal(int n) < std::cout void printRef(int& n)
Здесь определены две практически идентичные функции. Только функция printVal получает параметр по значению, а функция printRef - по ссылке. При вызове в обе функции передается число типа double . Но параметр обоих функций представляет тип int . И если при передаче по значению переданное число double успешно преобразуется в int (пусть и с потерей точности), то при передаче по ссылке мы столкнемся с ошибкой на этапе компиляции. Это еще одна причина, почему нередко рекомендуется передавать значения по ссылки - исключается вероятность предвиденных и иногда нежелательных преобразований типов.
Создание передачи по ссылке
Хотя, как правило, передача параметров в С происходит по значению, можно передать параметр по ссылке. Поскольку в данном случае происходит передача адреса аргумента, возможно изменение значения аргумента, находящегося вне функции.
Указатели передаются в функции как и обычные значения. Конечно, необходимо объявлять параметры типа указатель. Ниже приведена функция swap(), обменивающая значение двух целочисленных аргументов:
void swap (int *x, int *y)
int temp;
temp = *x; /* сохранение значения по адресу х */
*х = *у; /* помещение у в х */
*у = temp; /* помещение х в у */
>Оператор * используется для доступа к переменным, на которые указывают операнды. Следовательно, содержимое переменных, используемых при вызове функции, обменивается.
Важно помнить, что swap() (или любая другая функция, использующая указатели на параметры) должна вызываться с адресами аргументов. Следующая программа демонстрирует правильный способ вызова swap():
void swap (int *x, int *y);
int main(void)
int x, y;
x = 10;
у = 20;
swap(&x, &y);
printf ("%d %d", x, y);
return 0;
>В данном примере переменной х присваивается значение 10, а у значение 20. Затем вызывается swap() с адресами х и у. Унарный оператор & используется для получения адресов переменных. Поэтому в функцию swap() передаются адреса х и у, а не их значения.