Тема 1. Описание функции

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

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

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

В Си верно также и такое определение: Функция - это группа операторов у которой есть имя.

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

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

Объявление функции

До того, как функция будет вызвана, она должна быть объявлена.

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

Объявление функции называют также её прототипом.

Схема:

Тип_результата Имя_функции (Тип_пар1, Тип_пар2, ...);
  • Тип_результата — некоторый существующий (например, встроенный) тип данных или ключевое слово void, указывающее на то что функция никакого значения возвращать не будет.
  • Имя_функции — уникальный для данного пространства имён идентификатор.
  • Тип_парN — некоторый существующий (например, встроенный) тип данных для N-oro аргумента.

Примеры:

int max (int, int);
double cube (double);
float massa();
void printarr(*int, int);

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

Если функция не возвращает никакого результата, т. е. объявлена с типом возвращаемого значения void, ее вызов не может быть использован как операнд более сложного выражения (например, значение такой функции нельзя чему-то присвоить).

Определение (описание) функции

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

Схема:

Тип_результата Имя_функции (Тип_пар1 Имя_пар1, Тип_пар2 Имя_пар2, ...) {
  Оператор1;
  Оператор2;
  ...
  ОператорN;
  return n;
};
  • Имя_парN — уникальное внутри функции имя N-ro параметра. Имена параметров можно задавать и в прототипе функции, тогда в определении надо использовать те же имена.
  • ОператорN — некоторые операторы и выражения, содержащиеся внутри функции и выполняющиеся каждый раз при вызове функции. Внутри операторов мы можем обращаться к глобальным объектам программы; к локальным объектам, объявленным внутри функции; а также к аргументам функции.
  • return n — оператор, останавливающий работу функции и возвращающий n в качестве её значения (при этом тип переменной n должен соответствовать типу результата в заголовке функции). Наличие этого оператора обязательно для функции возвращающей значение. Для функции объявленной как void можно вызывать оператор return без аргументов, это досрочно завершит функцию, иначе — будут выполнены все действия до конца блока описания функции.

Одна функция не может объявляться или определяться внутри другой (т.е. нельзя объявлять и определять функции внутри main).

Пример объявления и описания функции:


int max (int, int);

int max (int n1,int n2) {
  if(nl > n2) {
    return n1;
  } else {
    return n2;
  }
}

int main(void) {
  int а = 100 - max(10,20);
  printf("a = %d",a);
  return 0;
}

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

Пример:


double cube (double a) {
  return a*a*a;
}

int main(void) {
  double pi = 3.1415;
  printf("Volume is %lf", cube(pi));
  return 0;
}

Но отдельно прототип указывают в тех случаях, когда функция будет описываться позже своего использования. Например, можно было объявить функцию до main, вызвать её из main, но описать только после main.

Пример:

double cube (double);

int main(void) {
  double pi = 3.1415;
  printf("Volume is %lf", cube(pi));
  return 0;
}

double cube (double a) {
  return a*a*a;
}

Такая возможность позволяет создавать модульные программы, исходный код которых может храниться даже в разных файлах.