Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Вызов функции
Вызов функции имеет следующий формат:
адресное-выражение ([список-выражений])
Поскольку синтаксически имя функции является адресом начала тела функции, в качестве обращения к функции может быть использовано адресное-выражение (в том числе и имя функции или разадресация указателя на функцию), имеющее значение адреса функции. Список-выражений представляет собой список фактических параметров, передаваемых в функцию. Этот список может быть и пустым, но наличие круглых скобок обязательно. Фактический параметр может быть величиной любого основного типа, структурой, объединением, перечислением или указателем на объект любого типа. Массив и функция не могут быть использованы в качестве фактических параметров, но можно использовать указатели на эти объекты. Выполнение вызова функции происходит следующим образом: 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. В противном случае, т.е. когда указателю на функцию присваивается функция описанная иначе чем указатель, произойдет ошибка. Рассмотрим пример использования указателя на функцию в качестве параметра функции вычисляющей производную от функции cos(x). Пример:
double proiz(double x, double dx, double (*f)(double x)); double fun(double z); int main() { double x; /* точка вычисления производной */ double dx; /* приращение */ double z; /* значение производной */ scanf("%f,%f",&x,&dx); /* ввод значений x и dx */ z=proiz(x,dx,fun); /* вызов функции */ printf("%f",z); /* печать значения производной */ return 0; } double proiz(double x,double dx, double (*f)(double z)) { /* функция вычисляющая производную */ double xk,xk1,pr; xk=fun(x); xk1=fun(x+dx); pr=(xk1/xk-1e0)*xk/dx; return pr; } double fun(double z) { /* функция от которой вычисляется производная */ return (cos(z)); }
Для вычисления производной от какой-либо другой функции можно изменить тело функции fun или использовать при вызове функции proiz имя другой функции. В частности, для вычисления производной от функции cos(x) можно вызвать функцию proiz в форме
z=proiz(x,dx,cos);
а для вычисления производной от функции sin(x) в форме
z=proiz(x,dx,sin);
Любая функция в программе на языке СИ может быть вызвана рекурсивно, т.е. она может вызывать саму себя. Компилятор допускает любое число рекурсивных вызовов. При каждом вызове для формальных параметров и локальных переменных выделяется новая область памяти, так что их значения из предыдущих вызовов не теряются, но в каждый момент времени доступны только значения текущего вызова. Переменные, объявленные с классом памяти static, не требуют выделения новой области памяти при каждом рекурсивном вызове функции и их значения доступны в течение всего времени выполнения программы. Классический пример рекурсии - это математическое определение факториала n!:
n! = 1 при n=0; n*(n-1)! при n>1.
Функция, вычисляющая факториал, будет иметь следующий вид:
long fakt(int n) { return ((n==1)? 1: n*fakt(n-1)); }
Хотя компилятор языка СИ не ограничивает число рекурсивных вызовов функций, это число ограничивается ресурсом памяти компьютера и при слишком большом числе рекурсивных вызовов может произойти переполнение стека. При вызове функции с переменным числом параметров в вызове этой функции задается любое требуемое число аргументов. В объявлении и определении такой функции переменное число аргументов задается многоточием в конце списка формальных параметров или списка типов аргументов. Все аргументы, заданные в вызове функции, размещаются в стеке. Количество формальных параметров, объявленных для функции, определяется числом аргументов, которые берутся из стека и присваиваются формальным параметрам. Программист отвечает за правильность выбора дополнительных аргументов из стека и определение числа аргументов, находящихся в стеке. Примерами функций с переменным числом параметров являются функции из библиотеки функций языка СИ, осуществляющие операции ввода-вывода информации (…printf, …scanf и т.п.). Date: 2015-12-12; view: 378; Нарушение авторских прав |