Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кетков.doc
Скачиваний:
17
Добавлен:
27.09.2019
Размер:
2.22 Mб
Скачать

Раздел 6. Основные синтаксические конструкции языка c

6.1. Заголовок функции и прототип функции

Любая программная единица на языках C, C++ оформляется как функция, причем в отличие от языка Pascal функции не могут быть вложены друг в друга. Поэтому функция представляется как некий кирпичик, который может быть размещен в любом месте программы. А вся программа состоит из последовательности таких кирпичиков, среди которых обязательно присутствует главный – функция с именем main.

Описание любой функции начинается с ее заголовка, имеющего вид:

trv namef(type1 par1,type2 par2,...)

Здесь trv – тип возвращаемого значения;

namef – имя функции;

par1 – имя первого аргумента функции, имеющего тип type1;

par2 – имя второго аргумента функции, имеющего тип type2;

………………………………………………………….

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

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

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

  • по указателю (в заголовке функции имени параметра предшествует символ *);

  • по ссылке (в заголовке функции имени параметра предшествует символ &).

Пример 1. Функции передаются два значения, по которым она находит и возвращает среднее арифметическое.

double mid(double x,double y)

{ return (x+y)/2.0; }

Пример 2. Функции передаются два параметра по указателю. Функция меняет местами значения переданных ей переменных.

void swap(int *x,int *y)

{ int tmp;

tmp=*x; *x=*y; *y=tmp;

}

Пример 3. Функции передаются два параметра по ссылке. Функция меняет местами значения переданных ей переменных.

void swap(float &x,float &y)

{ float tmp;

tmp=x; x=y; y=tmp;

}

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

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

Пример 4. Заголовки функций вынесены в список прототипов.

double mid(double x, double y);

void swap1(double *x,double *y);

void swap2(double &x,double &y);

void main()

{ double a=1.5, b=-2.5,c;

c=mid(a,b);

swap1(&a,&b);

swap2(b,c);

.............

}

double mid(double x, double y)

{ return (x+y)/2.0; }

void swap1(double *x,double *y)

{ double tmp;

tmp=*x; *x=*y; *y=tmp;

}

void swap2(double &x,double &y)

{ double tmp;

tmp=x; x=y; y=tmp;

}

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

double mid(double, double);

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

int intersect(double&,double&,double&,double&,double&,double&);

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

int intersect( double &x1, double &y1, double &x2, double &y2,

double &x, double &y);