Функции : вызов функции, возвращаемое значение

Функции

Функция — это самостоятельная единица программы, которая спроектирована для реализации конкретной подзадачи.

Функция является подпрограммой, которая может содержаться в основной программе, а может быть создана отдельно (в библиотеке). Каждая функция выполняет в программе определенные действия.

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

Семантика функции определяет способ реализации функции. Обычно представляет собой тело функции.

Определение функции

Каждая функция в языке Си должна быть определена, то есть должны быть указаны:

  • тип возвращаемого значения;
  • имя функции;
  • информация о формальных аргументах;
  • тело функции.

Определение функции имеет следующий синтаксис:

 
 
 
 
 
 
ТипВозвращаемогоЗначения ИмяФункции(СписокФормальныхАргументов)
{
   ТелоФункции;
  …
  return(ВозвращаемоеЗначение);
}

Пример: Функция сложения двух вещественных чисел

1
2
3
4
5
6
float function(float x, float z)
{
  float y;
  y=x+z;
  return(y);
}

В указанном примере возвращаемое значение имеет тип float. В качестве возвращаемого значения в вызывающую функцию передается значение переменной y. Формальными аргументами являются значения переменных x и z.

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

Если функция не принимает аргументов, в круглых скобках также указывается void.

Различают системные (в составе систем программирования) и собственные функции.

Системные функции хранятся в стандартных библиотеках, и пользователю не нужно вдаваться в подробности их реализации. Достаточно знать лишь их сигнатуру. Примером системных функций, используемых ранее, являются функции printf() и scanf().

Собственные функции — это функции, написанные пользователем для решения конкретной подзадачи.

Разбиение программ на функции дает следующие преимущества:

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

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

Вызов функции

Общий вид вызова функции

 
Переменная = ИмяФункции(СписокФактическихАргументов);

Фактический аргумент — это величина, которая присваивается формальному аргументу при вызове функции. Таким образом, формальный аргумент — это переменная в вызываемой функции, а фактический аргумент — это конкретное значение, присвоенное этой переменной вызывающей функцией. Фактический аргумент может быть константой, переменной или выражением.

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

Возврат в вызывающую функцию

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

Функция может передать в вызывающую программу только одно значение. Для передачи возвращаемого значения в вызывающую функцию используется оператор return в одной из форм:

 
return(ВозвращаемоеЗначение);
 
return ВозвращаемоеЗначение;

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

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

Функции могут и не возвращать значения, а просто выполнять некоторые вычисления. В этом случае указывается пустой тип возвращаемого значения void, а оператор return может либо отсутствовать, либо не возвращать никакого значения:

 
return;

Пример: Посчитать сумму двух чисел.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf
#include <stdio.h>
// Функция вычисления суммы двух чисел
int sum(int x, int y) // в функцию передаются два целых числа
{
  int k = x + y;  // вычисляем сумму чисел и сохраняем в k
  return k;       // возвращаем значение k
}
int main()
{
  int a, r;      // описание двух целых переменных
  printf("a= ");
  scanf("%d", &a); // вводим a
  r = sum(a, 5);    // вызов функции: x=a, y=5
  printf("%d + 5 = %d", a, r); // вывод: a + 5 = r
  getchar(); getchar(); // мы использовали scanf(),
  return 0;  // поэтому getchar() вызываем дважды
}

Результат выполнения

Сумма двух чисел

В языке Си нельзя определять одну функцию внутри другой.

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

  • тип возвращаемого значения;
  • имя функции;
  • типы формальных аргументов в порядке их следования.

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

Если в примере выше тело функции сложения чисел разместить после тела функции main, то код будет выглядеть следующим образом:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf
#include <stdio.h>
int sum(intint);   // сигнатура
int main() 
{
  int a, r;
  printf("a= ");
  scanf("%d", &a);
  r = sum(a, 5);    // вызов функции: x=a, y=5
  printf("%d + 5 = %d", a, r);
  getchar(); getchar();
  return 0;
}
int sum(int x, int y) // семантика
{
  int k;              
  k = x + y;
  return(k);
}

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

Пример: поменять местами два числа.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
void swap(int* a, int* b)   // аргументы передаются через указатели
{
  int temp = *a;      
  *a = *b;
  *b = temp;
  return;
}
int main()
{
  int a = 3, b = 5;
  printf("a=%d b=%d\n", a, b);
  swap(&a, &b);         // передаем в функцию адреса переменных a и b
  printf("a=%d b=%d\n", a, b);
  getchar(); getchar();
  return 0;
}

Результат выполнения

Поменять местами два числа

Рекурсивные функции

Функция, которая вызывает сама себя, называется рекурсивной функцией.

Рекурсия — вызов функции из самой функции.

Пример рекурсивной функции — функция вычисления факториала.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS // для возможности использования scanf
#include <stdio.h>
int fact(int num)  // вычисление факториала числа num
{
  if (num <= 1)   return 1;  // если число не больше 1, возвращаем 1
  else return num*fact(num - 1);  // рекурсивный вызов для числа на 1 меньше
}
// Главная функция
int main() 
{
  int a, r;
  printf("a= ");
  scanf("%d", &a);
  r = fact(a);    // вызов функции: num=a
  printf("%d! = %d", a, r);
  getchar(); getchar();
  return 0;
}

Результат выполнения

Более подробно рекурсивные функции рассмотрены в этой статье.

Математические функции

Математические функции хранятся в стандартной библиотеке math.h. Аргументы большинства математических функций имеют тип double. Возвращаемое значение также имеет тип double. Углы в тригонометрических функциях задаются в радианах.

Основные математические функции стандартной библиотеки.

Функция Описание
int abs(int x) Модуль целого числа x
double acos(double x) Арккосинус x
double asin(double x) Арксинус x
double atan(double x) Арктангенс x
double cos(double x) Косинус x
double cosh(double x) Косинус гиперболический x
double exp(double x) Экспонента x
double fabs(double x) Модуль вещественного числа
double fmod(double x, double y) Остаток от деления x/y
double log(double x) Натуральный логарифм x
double log10(double x) Десятичный логарифм x
double pow(double x, double y) x в степени y
double sin(double x) Синус x
double sinh(double x) Синус гиперболический x
double sqrt(double x) Квадратный корень x
double tan(double x) Тангенс x
double tanh(double x) Тангенс гиперболический x

Особенности использования функций в языке C++ рассмотрены в этой статье.

Прокрутить вверх