Функция - это самостоятельная единица программы, созданная для решения одной задачи. Функция в языке С играет ту же роль, что и подпрограммы или процедуры в других языках. Функциями удобно пользоваться, например, если необходимо обработать один и тот же код программы. Как и переменные, функции надо объявлять (declare). Функцию необходимо объявить до её использования. Запомните это простое правило - сначала объяви, а потом используй.
Все функции языка С имеет имя и список аргументов (формальных параметров).
Основная форма описания (definition) функции имеет вид:
тип <имя функции>(список параметров)
{
тело функции
}
Объявление (прототип) функции имеет вид:
тип <имя функции>(список параметров);
Обратите внимание на то, что при описании функции после заголовка функции
тип <имя функции>(список параметров)
точка с запятой не ставиться, а при объявлении функции точка с запятой ставиться.
Вызов функции делается следующим образом:
<имя функции>(параметры);
или
<переменная>=<имя функции>(параметры);
При вызове функции так же ставиться точка с запятой.
Почему надо объявлять функцию до использования? Дело в том, что для правильной работы кода функции машине надо знать тип возвращаемого значения, количество и типы аргументов. При вызове какой-либо функции копии значений фактических параметров записываются в стек, в соответствии с типами указанными в ее прототипе. Затем происходит переход в вызываемую функцию.
Приведем пример вызова функции, которая будет печатать строку "Вызвали функцию" на экран.
/* Используем свою функцию */
#include <stdio.h>
void main(void) // Точка входа в программу
{
void function1(void); // Объявление функции
function1(); // Вызов функции
}
/* Описание функции */
void function1(void) // Заголовок функции
{ // Начало тела функции
printf("Вызвали функцию\n");
} // Конец тела функции
Результатом работы программы будет строка напечатанная на экране.
Обратите внимание на заголовок в описании функции! После него не ставится точка с запятой.
В теле функции main() мы объявили функцию function1(), затем её вызвали. В теле нашей функции function1() мы вызываем функцию printf(). А где же объявлена функция printf() ? Если вы внимательно посмотрите текст программы, то увидите строку #include <stdio.h>, как говорилось ранее эта строка говорит компилятору, чтобы тот включил в текст программы файл с объявлениями функций стандартного ввода/вывода (standart input/output). Аха! Значит функция printf() объявлена именно там!
Директива препроцессора (preprocessor directive) просто вставляет текстовый файл stdio.h в текст нашей программы. Причем вставляет туда где стоит эта директива. Если вы уберете или закоментируете строку #include <stdio.h>, то программа работать не будет потому что функция printf() не будет объявлена. Компилятор просто выдаст ошибку - Function 'printf' should have a prototype (Функция 'printf' должна иметь прототип).
необходимо обратить внимание на то, что тип возвращаемого значения у нашей функции void (пусто). Это значит, что функция не будет возвращать никакого значения.
Давайте рассмотрим пример в котором опишем две функции, соответственно объявим их и последовательно вызовем. Но в этом примере для одной функции мы укажем тип возвращаемого значения - int.
/* Две наших функции */
#include <stdio.h> // Подключаем файл заголовков функций (их объявлений)
int x; // Объявляем переменную x (глобальная переменная)
void main(void)
{
void function1(void); // Объявляем функцию function1()
int function2(); // function2() будет возвращать значение типа int
x = 10; // Присваиваем переменной x значение 10
printf("До вызова функции function2() x равно %d\n", x);
function1(); // Вызываем функцию function1()
x = function2(); // Вызываем функцию function2()
printf("После вызова функции function2() x равно %d\n", x);
}
/* Описание наших функций */
void function1(void)
{
printf("Сделан вызов первой функции\n");
}
int function2(void)
{
int y; // Объявляем локальную переменную
y = x + 10;
return y; // Возвращаем значение y
}
Теперь давайте посмотрим текст программы. После строки #include <stdio.h> мы объявляем глобальную переменную x. Так как x - глобальная переменная, то она будет видна всем функция нашей программы т.е. этой переменной могут пользоваться все функции.
В теле main() мы объявляем две функции, одна из которых может возвращать значение типа int. Далее мы присваиваем переменной x значение 10, так как x это глобальная переменная, то эта переменная будет видна функции main() т.е. функция main() может использовать эту переменную. После этого присвоения мы выводим значение x на экран.
На экране монитора появится следующая строка - "До вызова функции function2() x равно 10".
Обратите внимание на вызов функции printf() -
printf("До вызова функции function2() x равно %d\n", x);
В строке после сиволов %d стоит символ \n. \n - управляющий символ он означает, что необходимо перейти на новую строку.
Далее мы вызываем функцию function1(). Эта функция просто выводит строку "Сделан вызов первой функции\n" на экран и так как в строке стоит \n, то будет осуществлен переход на новую строку.
В следующей строке x = function2(); переменная x принимает значение которое вернет функция function2(). Посмотрите на описание функции function2(). В теле этой функции мы объявляем переменную y, а дальше переменной y мы присваиваем значение переменной x + 10. Так как x - глобальная переменная (она видна для функции function2) все будет работать.
Далее идет строка return y; с помощью оператора return мы возвращаем значение переменной y. Запомните, что если функция возвращает значение, то в теле этой функции обязательно должен присутствовать оператор return (он может быть и не один). Ну так вот с помощью оператора return мы возвращаем значение локальной переменной y в вызывающую функцию main().
Теперь посмотрим тело функции main() Следующей строкой после x = function2(); является строка printf("После вызова функции function2() x равно %d\n", x); которая выводи значение измененной переменной x;
На экране появится строка - "После вызова функции function2() x равно 20".
Функции с параметрами.
Функции языка С могут иметь параметры. Эти параметры передаются в функцию и там обрабатываются. Ещё раз покажем основную форму описания функции
тип <имя функции>(список параметров)
{
тело функции
}
В списке параметров для каждого параметра должен быть указан тип.
Пример правильного списка параметров:
function(int x, char a, float z)
Пример неправильного списка параметров:
function(int x, a, float z)
Давайте рассмотрим все это на примере. Пусть у нас будет функция у которой присутствует один параметр x. Функция будет возвращать квадрат значения x.
int square(int x)
{
x = x * x; // Символ * это операция умножения
return x;
}
Теперь давайте рассмотри пример функции, которая будет выводить значение переменной z типа float на экран.
void myout(float z) // Переменная z является формальным параметром.
{
printf("Z=%f", z); // %f - означает, что выводится число с плавающей точкой
}
Формальные и фактические параметры
Формальные параметры - это параметры которые мы объявляем в заголовке функции при описании.
Фактические параметры - это параметры которые мы подставляем при вызове функции.
void myfunc(int x); // Объявление функции
void main(void)
{
int a;
a=5;
myfunc(a); // a- фактический параметр
}
// Описание функции
void myfunc(int x) // x - формальный параметр
{
x = x + 10;
printf("Вывод x = %d",x);
}
Функция может возвращать не только одно значение, а несколько значений. Чтобы функция вернула несколько значений надо пользоваться указателями - передача параметров по ссылке. Указатели это сложная тема, которую мы подробно распишем на следующих уроках.