Функции. Вызов функций: вызов по значению и по ссылке. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Функции. Вызов функций: вызов по значению и по ссылке.



вызов функции имеет следующий формат:

адресное-выражение ([список-выражений])

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

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

список может быть и пустым, но наличие круглых скобок обязательно.

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

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

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

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

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

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

3. Управление передается на первый оператор функции.

4. Выполнение оператора return в теле функции возвращает управление и возможно, значение в

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

Пример:

int (*fun)(int x, int *y);

Здесь объявлена переменная fun как указатель на функцию сдвумя параметрами: типа int и указателем

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

fun и признак указателя *, обязательны, иначе запись int *fun (intx,int *y);

будет интерпретироваться как объявление функции fun, возвращающей указатель на int.

Вызов функции возможен только после инициализации значения указателя fun и имеет вид: (*fun)(i,&j);

В этом выражении для получения адреса функции, на которую ссылается указатель fun, используется операция разадресации *.

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

указателю на функцию можно в операторе присваивания, употребив имя функции без списка параметров.

Пример:

double (*fun1)(int x, int y);

double fun2(int k, int l);

fun1=fun2; // инициализация указателя на функцию (*fun1)(2,7); // обращение к функции

В рассмотренном примере указатель на функцию fun1 описан как указатель на функцию с двумя параметрами, возвращающую значение типа double, и также описана функция fun2. В противном случае,т.е. когда указателю на функцию присваивается функция, описанная иначе, чем указатель, произойдет ошибка.

33. Рекурсия. Функция называется рекурсивной, если во время ее обработки возникает ее повторный вызов, либо

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

int a()

{.....a().....}

Любая функция в программе на языке С может быть вызвана рекурсивно, т.е. она может вызывать саму

себя. Компилятор допускает любое число рекурсивных вызовов. При каждом вызове для формальных

параметров и переменных с классом памяти auto и register выделяется новая область памяти, так что

их значения из предыдущих вызовов не теряются, но в каждый момент времени доступны только значения

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

программы.

Классический пример рекурсии – это математическое определение факториала n!:

n! = 1 при n=0;

n*(n-1)! при n>1.

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

long fakt(int n)

{return ((n==1)? 1: n*fakt(n-1)); }

Хотя компилятор языка С не ограничивает число рекурсивных вызовов функций, это число

ограничивается ресурсом памяти компьютера и при слишком большом числе рекурсивных вызовов

может произойти переполнение стека.

If, #else, #elif

Имеется несколько директив, которые дают возможность выборочно компилировать части исходного кода вашей программы.

Возможно, самыми распространенными директивами условной компиляции являются #if, #else, #elif и #endif. Они дают возможность в зависимости от значения константного выражения включать или исключать те или иные части кода.

В общем виде директива #if выглядит таким образом:

#if константное выражение

последовательность операторов

#endif

Если находящееся за #if константное выражение истинно, то компилируется код, который находится между этим выражением и #endif. В противном случае этот промежуточный код пропускается. Директива #endif обозначает конец блока #if.

Директива #else работает в основном так, как else — ключевое слово языка С: задает альтернативу на тот случай, если не выполнено условие #if.

Директива #elif означает "else if" и устанавливает для множества вариантов компиляции цепочку if-else-if. После #elif находится константное выражение. Если это выражение истинно, то компилируется находящийся за ним блок кода, и больше не проверяются никакие другие выражения #elif. В противном же случае проверяется следующий блок этой последовательности. В общем виде #elif выглядит таким образом:

#if выражение

последовательность операторов

#elif выражение 1

последовательность операторов

#elif выражение 2

последовательность операторов

#elif выражение 3

последовательность операторов

#elif выражение 4

.

#elif выражение N

последовательность операторов

#endif

Другой способ условной компиляции — это использование директив #ifdef и #ifndef, которые соответственно означают "if defined" (если определено) и "if not defined" (если не определено). В общем виде #ifdef выглядит таким образом:

#ifdef имя_макроса

последовательность операторов

#endif

Блок кода будет компилироваться, если имя макроса было определено ранее в операторе #define.

В общем виде оператор #ifndef выглядит таким образом:

#ifndef имя_макроса

последовательность операторов

#endif

Блок кода будет компилироваться, если имя макроса еще не определено в операторе #define.

 

35.

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

Замена идентификаторов
#define идентификатор строка
Пример:
#define ABC 100
Заменяет каждое вхождение идентификатора ABC в тексте программы на 100:
#undef идентификатор
Пример:
#undef ABC
Отменяет предыдущее определение для идентификатора ABC.

 

32.



Поделиться:


Последнее изменение этой страницы: 2016-04-07; просмотров: 433; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.145.151.141 (0.01 с.)