тип имя_функции (пар_инф1, пар_инф2, …);

где параметр пар_инфi – информация о имени и типе формальных параметров.

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

тип имя_функции (имена параметров )

определение параметров;

{

локальные описания;

операторы;

}

Формат описания в современном стиле предусматривает определение параметров функции в скобках, следующих за именем функции:

тип имя_функции (пар_инф, пар_инф, …)

где определение параметра пар_инф – содержит информацию о передаваемом параметре: тип и идентификатор.

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

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

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

Результат выполнения функции возвращается при помощи оператора return. Общий вид:

Return (выражение);

Оператор завершает выполнение функции и передает управление следующему оператору в вызывающей функции. Это происходит даже в том случае, если оператор return является не последним оператором тела функции.

НЕ нашли? Не то? Что вы ищете?

Можно использовать оператор return в виде:

return; return 0;

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

main( )

{ float y, x, mult( ); /* описание в вызывающей программе */

int n;

………

y=mult(x, n);

………}

float mult(v, k) /* описание в определении функции */

float v;

int k;

{ float res;

for (res=0.0; k>0; k--)

res=res*v;

return (res); } /* возвращает значение типа float */

С помощью оператора return в вызывающую программу можно передать только одну величину. Если нужно передать две величины, нужно воспользоваться указателями.

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

[<спецификация КП>][<спецификация типа>]<описатель>([<список параметров>]) [<объявление параметров>] <тело функции>

Спецификация класса памяти <спец. КП> задает класс памяти функции.

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

Современная конструкция:

[<спецификация КП>][<спецификация типа>]<описатель>([<список объявлений параметров>])<тело функции>

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

[<спецификация КП>][<спецификация типа>]<описатель>([<список типов аргументов>]);

Объявление функции специфицирует имя функции, тип возвращаемого значения и, возможно, типы ее аргументов и их число.

Современный стиль описания (объявление прототипов). В списке типов аргументов прототип может содержать также и идентификаторы этих аргументов.

float f1(float a, float b)

{ float c;

c=(2*pow(a,3)+sin a)/pow(a+b,4);

return c; }

main( )

{ float x, y,s=0;

clrscr ( );

printf (“\n Введите x, y”);

scanf (“%f %f ”, &x, &y);

s=f1(5.6, y)+f1(2*x-1, x*y);

printf(“\n s=%6.2f ”,s);

return 0; }

Адресные операции. Си поддерживает две специальные адресные операции: операцию определения адреса (&) и операцию обращения по адресу (*). Операция & возвращает адрес данной переменной. Если sum является переменной типа int, то &sum является адресом этой переменной.

Указатели. Указатель является переменной, которая содержит адрес некоторых данных. Вообще говоря, указатель – это некоторое символическое представление адреса. &sum в данном случае означает «указатель на переменную sum». Фактическим адресом является число, а символическое представление адреса &sum является константой типа указатель. Т. обр. адрес ячейки памяти, отводимой переменной sum в процессе выполнения программы не меняется.

В языке Си имеются и переменные типа указатель. Значением переменной типа указатель служит адрес некоторой величины. Пусть указатель обозначен идентификатором ptr, тогда оператор следующего вида присваивает адрес sum переменной ptr: ptr=&sum. В этом случае говорят, что ptr «указывает на» sum. Итак, ptr – переменная, &sum – константа. Переменная ptr может указывать на какой-нибудь другой объект:

ptr=&max

Значением ptr является адрес переменной max. Рассмотрим операцию обращения по адресу (*) или операцию косвенной адресации. предположим в переменной ptr соержится ссылка на переменную max. Тогда для доступа к значению этой переменной можно воспользоваться операцией обращения по адресу (*). Для определения значения, на которое указывает ptr запишем следующий оператор:

Res=*ptr; (Последние два оператора, взятые вместе, эквивалентны следующему: Res=max;)

Использование операции получения адреса и косвенной адресации оказывается далеко не прямым путем к результату, отсюда и появление слова «косвенная» в названии операции.).

Операция (*) – когда за этим знаком следует указатель на переменную, результатом операции является величина, помещенная в ячейку с указанным адресом.

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

int * iptr;

char * cptr;

float * fptr;

Использование указателей для связи между функциями. Рассмотрим пример использования указателей для установления связи между функциями. В данном примере указатели используются для обмена значений переменных.

main()

{ int x=5, y=10;

printf (“x=%d y=%d\n”, x, y);

change (&x, &y); /*передача адресов функции*/

printf (“x=%d y=%d\n”, x, y); }

change (u, v)

int *u, *v; /*u и v являются указателями*/

{ int temp;

temp=*u; /*temp присваивается значение, на которое указывает u*/

*u=*v;

*v=temp; }

Данная функция изменяет значения переменных x и y. Путем передачи функции адресов переменных х и у мы предоставили ей возможность доступа к ним. Используя указатели и операцию (*), функция смогла извлечь величины, помещенные в соответствующие ячейки памяти, и поменять их местами.

Основная литература: 1осн[173-205], 2осн[256-290]

Дополнительная литература: 10доп[51-54]

Контрольные вопросы:

1. Могут ли имена формальных и фактических параметров подпрограмм совпадать между собой?

2. В чем состоит отличие описания процедуры и функции?

3. Какие параметры называются формальными и какие – фактическими?

4. Какие существуют стили описания и определения функций?

5. Назовите оператор для возвращения результата выполнения функции?

Тема 6. Классы памяти и разработка программ.

Класс памяти определяет область действия переменной и продолжительность ее существования в памяти. Класс памяти устанавливается при описании переменной с соответствующим ключевым словом. Ранее при рассмотрении функций было отмечено, что переменные, описанные в функции как локальные переменные, доступны только внутри функции. Для того, чтобы использовать переменную в нескольких функциях, необходимо описать ее как внешнюю переменную. Переменные, определенные вне функции, являются внешними и имеют глобальную область действия. Каждая переменная имеет тип, а также она принадлежит к некоторому классу памяти. Для описания классов памяти используется четыре ключевых слова: для описания внешнего класса используется ключевое слово extern, для автоматического класса – слово auto, для описания статического класса – слово statiс и для описания регистрового класса – register. Рассмотрим свойства переменных, относящихся к определенному классу памяти.

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

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

int l;

main()

{ extern int l;

scanf(“%d”,&l);

while(l!=20)

pr();

printf(“Поиск завешен \n”); }

pr()

{ extern int l;

printf(“Введите новое число \n”);

scanf(“%d”,&l); }

Если в функции pr() описание переменной l будет отсутствовать, внешняя переменная l будет известна в функции pr() по умолчанию. Если в функции main() и функции pr() ключевое слово extern не будет включено в описание переменной l внутри функции, то под этим именем создается новая автоматическая переменная. Внешняя переменная l не известна будет этим функциям. Если слово extern опущено в описании переменной l в функции pr(), тогда переменная l, которая находится в main() функции, никогда не получит нового значения.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27