Функция — это самостоятельная единица программы, которая спроектирована для реализации конкретной подзадачи.
Функция является подпрограммой, которая может содержаться в основной программе, а может быть создана отдельно (в библиотеке). Каждая функция выполняет в программе определенные действия.
Сигнатура функции определяет правила использования функции. Обычно сигнатура представляет собой описание функции, включающее имя функции, перечень формальных параметров с их типами и тип возвращаемого значения.
Семантика функции определяет способ реализации функции. Обычно представляет собой тело функции.
Определение функции
Каждая функция в языке Си должна быть определена, то есть должны быть указаны:
- тип возвращаемого значения;
- имя функции;
- информация о формальных аргументах;
- тело функции.
Определение функции имеет следующий синтаксис:
{
ТелоФункции;
...
return(ВозвращаемоеЗначение);
}
Пример: Функция сложения двух вещественных чисел
2
3
4
5
6
{
float y;
y=x+z;
return(y);
}
В указанном примере возвращаемое значение имеет тип float. В качестве возвращаемого значения в вызывающую функцию передается значение переменной y. Формальными аргументами являются значения переменных x и z.
Если функция не возвращает значения, то тип возвращаемого значения для нее указывается как void. При этом операция return может быть опущена. Если функция не принимает аргументов, в круглых скобках также указывается void.
Различают системные (в составе систем программирования) и собственные функции.
Системные функции хранятся в стандартных библиотеках, и пользователю не нужно вдаваться в подробности их реализации. Достаточно знать лишь их сигнатуру. Примером системных функций, используемых ранее, являются функции printf() и scanf().
Собственные функции — это функции, написанные пользователем для решения конкретной подзадачи.
Разбиение программ на функции дает следующие преимущества:
- Функцию можно вызвать из различных мест программы, что позволяет избежать повторения программного кода.
- Одну и ту же функцию можно использовать в разных программах.
- Функции повышают уровень модульности программы и облегчают ее проектирование.
- Использование функций облегчает чтение и понимание программы и ускоряет поиск и исправление ошибок.
С точки зрения вызывающей программы функцию можно представить как некий «черный ящик», у которого есть несколько входов и один выход. С точки зрения вызывающей программы неважно, каким образом производится обработка информации внутри функции. Для корректного использования функции достаточно знать лишь ее сигнатуру.
Вызов функции
Общий вид вызова функции
Фактический аргумент — это величина, которая присваивается формальному аргументу при вызове функции. Таким образом, формальный аргумент — это переменная в вызываемой функции, а фактический аргумент — это конкретное значение, присвоенное этой переменной вызывающей функцией. Фактический аргумент может быть константой, переменной или выражением. Если фактический аргумент представлен в виде выражения, то его значение сначала вычисляется, а затем передается в вызываемую функцию. Если в функцию требуется передать несколько значений, то они записываются через запятую. При этом формальные параметры заменяются значениями фактических параметров в порядке их следования в сигнатуре функции.
Возврат в вызывающую функцию
По окончании выполнения вызываемой функции осуществляется возврат значения в точку ее вызова. Это значение присваивается переменной, тип которой должен соответствовать типу возвращаемого значения функции. Функция может передать в вызывающую программу только одно значение. Для передачи возвращаемого значения в вызывающую функцию используется оператор return в одной из форм:
Действие оператора следующее: значение выражения, заключенного в скобки, вычисляется и передается в вызывающую функцию. Возвращаемое значение может использоваться в вызывающей программе как часть некоторого выражения.
Оператор return также завершает выполнение функции и передает управление следующему оператору в вызывающей функции. Оператор return не обязательно должен находиться в конце тела функции.
Функции могут и не возвращать значения, а просто выполнять некоторые вычисления. В этом случае указывается пустой тип возвращаемого значения void, а оператор return может либо отсутствовать, либо не возвращать никакого значения:
Пример: Посчитать сумму двух чисел.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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, то код будет выглядеть следующим образом:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
int sum(int, int); // сигнатура
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);
}
Рекурсивные функции
Функция, которая вызывает сама себя, называется рекурсивной функцией.
Рекурсия — вызов функции из самой функции.
Пример рекурсивной функции — функция вычисления факториала.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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++ рассмотрены в этой статье.
Назад: Язык Си
2
3
4
5
6
7
8
9
10
11
void f1(void)
{
f(); /* первый вызов f() */
}
/* определение */
void f(void)
{
prinf("Hello from f()\n");
}
2
3
4
5
6
7
8
9
10
void f(void)
{
prinf("Hello from f()\n");
}
void f1(void)
{
f(); /* первый вызов f() */
}
2
3
4
5
6
7
8
9
10
11
12
13
#include<math.h>
int main()
{
double a,b,c;
scanf("%lf %lf %lf", &a, &b, &c);
double S;
double p = (a + b + c)/2.0;
S = sqrt(p * (p-a) * (p-b) * (p-c));
printf("%.2f\n", S);
return 0;
}
Выдает такую ошибку:
$ gcc ex01.c -o app /tmp/ccfxQVzx.o: In function `main': ex01.c:(.text+0x9b): undefined reference to `sqrt' collect2: error: ld returned 1 exit status (в чем подвох??????)
Судя по тексту ошибки, компилятор не может найти тело функции sqrt().
2
3
4
5
{
if (k % 2 == 0) return true;
return false;
}
2
3
return(25, "Saratov");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using namespace std;
void minimax(int a, int b, int c, int &min, int &max)
{
min = a;
max = a;
if (b < min) min = b;
else max = b;
if (c < min) min = c;
if(c > max) max = c;
return;
}
int main()
{
int min, max;
minimax(3, 8, 4, min, max);
cout << "min = " << min << endl;
cout << "max = " << max << endl;
cin.get();
return 0;
}
2
3
4
5
6
7
8
{}
float function(float x, float z)
{
float y;
y=x+z;
return (y);
}
2
3
4
{
printf("%f", function(3,2));
}
2
…
2
3
…
}