Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

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




Функции

Общие моменты

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

Функция - это совокупность объявлений переменных и операторов, обычно предназначенная для решения определенной задачи. Каждая функция должна иметь имя, которое используется для ее объявления, определения и вызова. В любой программе на СИ должна быть функция с именем main (главная функция), именно с этой функции, в каком бы месте программы она не находилась, начинается выполнение программы.

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

С использованием функций в языке СИ связаны три понятия:

ü определение функции (описание действий, выполняемых функцией),

ü объявление функции (задание формы обращения к функции) (прототип функции) (необязательно)

ü вызов функции.

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

В соответствии с синтаксисом языка СИ определение функции имеет следующую

форму:

[спецификатор-класса-памяти] [спецификатор-типа] имя-функции

([список-формальных-параметров])

{ тело-функции }

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

Функция возвращает значение если ее выполнение заканчивается оператором

return, содержащим некоторое выражение. Указанное выражение вычисляется,

преобразуется, если необходимо, к типу возвращаемого значения и возвращается в

точку вызова функции в качестве результата.

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

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

Тип формального параметра может быть любым основным типом, для которого определена операция присваивания.

Тело функции - это составной оператор, содержащий операторы, определяющие

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

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

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

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

[спецификатор-класса-памяти] [спецификатор-типа] имя-функции

([список-формальных-параметров]) [,список-имен-функций];

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

Прототип - это явное объявление функции, которое предшествует определениюфункции. Тип возвращаемого значения при объявлении функции должен

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

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

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

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

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

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

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).

Пример:

doubleproiz(double x, double dx, double (*f)(double x) );

double fun(double z);

int main()

{

double x;          /* точка вычисления производной */

doubledx;         /* приращение              */

double z;          /* значение производной    */

scanf("%f,%f",&x,&dx); /* ввод значений x и dx    */

z=proiz(x,dx,fun); /* вызов функции           */

printf("%f",z);    /* печать значения производной */

return 0;

}

doubleproiz(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;

returnpr;

}

double fun( double z)

{ /* функция от которой вычисляется производная */

return (cos(z));

}

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

функции fun или использовать при вызове функции proiz имя другой функции. В

частности, для вычисления производной от функции cos(x) можно вызвать функцию

proiz в форме

z=proiz(x,dx,cos);

а для вычисления производной от функции sin(x) в форме

z=proiz(x,dx,sin);

Рекурсия

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

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

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

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

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

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

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

Перегрузка функций

Перегрузка функций - возможность использования одноимённых функций, с различным функционалом в языках программирования.

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

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 293.

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