Тип_возвращаемого_значения имя_функции(список_параметров)

{

Тело функции

}

Тип_возвращаемого_значения определяет тип переменной, которую возвращает функция.

- спецификатор класса памяти – задает класс памяти функции, который может быть или static или extern;

- спецификатор типа и декларатор определяют тип возвращаемого значения и имя функции;

- список параметров - это список (возможно пустой) формальных параметров, которые используются функцией;

- объявления параметров задают типы формальных параметров;

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

Класс памяти

Спецификатор класса памяти в определении функции определяет функцию как static или extern. Функция с классом памяти static видима только в том исходном файле, в котором она определена. Все другие функции с классом памяти extern, заданным явно или неявно, видимы во всех исходных файлах, которые образуют программу. Если спецификатор класса памяти опускается в определении функции, то подразумевается класс памяти extern.

Тип возвращаемого значения

Спецификатор типа вместе с декларатором определяет тип возвращаемого значения и имя функции. Если не задан, то подразумевается, что тип int. Функции не могут возвращать массивов или функции, но они могут возвращать указатели на любой тип, включая массивы и функции. Тип используется только тогда, когда функция возвращает значение, которое вырабатывается, если выполняется оператор return, содержащий выражение. Выражение вычисляется, преобразуется к типу возврата, если это необходимо, и возвращается в точку вызова. Если оператор return не выполняется или если выполняемый оператор return не содержит выражения, то значение возврата функции не определено. Если в этом случае вызывающая функция ожидает значение возврата, то поведение программы также не определено. /*

Пример

*/ int add (int x,int y)

{

return (x+y);

}

/*

Формальные параметры

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

Тело функции

Тело функции – это просто составной оператор. Составной оператор содержит операторы, которые определяют действия функции, и может также содержать объявления переменных, используемых в этих операторах. Все переменные, объявленные в теле функции, имеют тип памяти auto, если они не объявлены иначе. Когда вызывается функция, то создается память для локальных переменных и производится их инициализация (если она задана). Управление передается первому оператору составного оператора и начинается процесс выполнения, который продолжается до тех пор, пока не встретится оператор return или конец тела функции. Управление при этом возвращается в точку вызова. Если функция возвращает значение, то должен быть выполнен оператор return, содержащий выражение. Значение возврата не определено, если не выполнен оператор return или если в оператор return не было включено выражение.

Фактические параметры

Фактическим параметром мы называем конкретное значение, передаваемое функции в момент вызова. В качестве них могут выступать константы или вычисляемые выражения. Все фактические аргументы передаются по значению. Копия фактических аргументов присваивается соответствующим формальным параметрам. Функция использует эти копии, не влияя на переменные, с которых копия была сделана. Путь доступа из функции к значениям оригинальных переменных обеспечивают указатели, т.к. указатель на переменную содержит адрес переменной, то функция может использовать этот адрес для доступа к значению переменной. Аргументы-указатели обеспечивают доступ из функции к массивам и функциям, которые запрещено передавать как аргументы. Несоответствие типов формальных и фактических параметров может привести к ошибкам, особенно когда несоответствие влечет за собой отличия в размерах. В этом случае могут происходить неявные преобразования, потеря точности и т.д.

Пример:

void swap (int *a, int *b);

{

int t;

t=*a;

*a=*b;

*b=t;

}

void main()

{

int x=5, y=6;

swap (&x,&y);

....

}

В примере функция swap объявлена как функция с двумя аргументами типа указателей на int. Формальные параметры a и b объявлены так же, как указатели на целые величины. При вызове функции адрес x запоминается в a и адрес y запоминается в b. Теперь два имени или "синонима" существует для одной и той же ячейки памяти. Ссылки *a и *b в функции swap действуют точно так же, как x и y в main. Присваивание внутри функции swap изменяет содержимое x и y.

Рекурсивные вызовы

Любая функция в С++ может быть вызвана рекурсивно. Для этого функция вызывает саму себя. Компилятор С++ допускает любое число рекурсивных вызовов, однако реально оно ограничивается размером стековой памяти. При каждом вызове формальных параметров и локальных переменных захватывается новая память, так что их значения из предшествующих незавершенных вызовов не перезаписываются. Предшествующие параметры недоступны в других версиях функции, исключая версию, в которой они были созданы. Заметим, что переменные, объявленные как глобальные, не требуют новой памяти при каждом рекурсивном вызове. Их память сохраняется на все время жизни программы.

Передача параметров

Передача параметров в функцию может осуществляться двумя способами: по ссылке и по значению. В отличие от других языков, например Visual Basic, в С++ по умолчанию происходит передача по значению. Это означает, что в функции создается локальная переменная, в которую копируется значение из внешней переменной.

Пример:

void fun(int a)

{

a=10; // присваиваем локальной переменной

}

void main()

{

int x=20;

fun(x); // не изменяем значение x

...

}

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

Пример:

void fun(int *a)

{

*a=10; // присваиваем переменной x новое значение

}

void main()

{

int x=20;

fun(&x); // изменяем значение x

...

}

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

Например:

void fun(int *a,int N)

{

for(int i=0; i<N; i++)

a[i]=i*i; // заполняем массив

}

void main()

{

int x[10];

fun(x,10);

...

}

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

Наши рекомендации