Выбрать главу

Второй: мы хотели показать, что не забыли те новые операции присваивания, которые ввели в гл. 8.

Третий: в соответствии с алгебраическими правилами возведение в отрицательную степень было преобразовано в деление. Это внесло опасность деления на нуль, но в данном случае мы предусмотрели выдачу сообщения об ошибке и возврат значения 0, чтобы работа программы не прекращалась.

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

/* проверка возведения в степень*/

main( )

{

double x;

double power( ); /* это пример oписания  функции */

x = power(2.0, 3);

printf(" %.0f \n", x);x = power(-3.0, 3);

printf(" %.0f\n" , x);x = power(4.0, -2);

printf(" %.4f\n", x);x = power(5.0, 10);

print f ("%.0f \n", x);

}

На этот раз результаты работы программы выглядят вполне удовлетворительно.

8

-27

0.0625

9765625

Данный пример побуждает нас ввести следующий короткий раздел.

ОПИСАНИЕ ТИПОВ ФУНКЦИЙ

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

1. Описать тип функции в ее определении:

char pun(ch, n) /* функция возвращает символ */

int n;

char ch; 

float raft(num) /* функция возвращает величину типа float */

int num;

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

main( )

{

char rch, pun( );

float raft;

}

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

Резюме: функции

1. Форма записи

Типичное определение функции имеет следующий вид:

имя (список аргументов)

описание аргументов

тело функции

Наличие списка аргументов и описаний не является обязательным. Переменные, отличные от аргументов, описываются внутри тела, которое заключается в фигурные скобки.

Пример:

diff(x, у)                 /* имя функции и список аргументов */

ini x, у;                 /* описание аргументов */

{                        /* начало тела функции */

int z;                /* описание локальной переменной */

z = х - у;return(z);

}                       /* конец тела функции */

II. Передача значений функции:

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

с = diff(а,b);

осуществляется передача этих значений переменным х и у. Значения 5 и 2 называют ся фактическими аргументами, а переменные х и у, указанные в описании функции: diff( ) - формальными аргументами.

     Использование ключевого слова return позволяет передавать в вызывающую программу одно значение из вызываемой функции. В нашем примере переменной с присваивается значение переменной z, равное 3.

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

III. Тип функции

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

Пример

main( )

{

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

int n;

...

q = duff(х, n);

...

}

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

float u;

int k;

{

float tor;

...

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

} 

В ЯЗЫКЕ СИ ВСЕ ФУНКЦИИ РАВНОПРАВНЫ

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

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

/* вызовфункции main( ) */

#include      

main( )

{

char ch;

printf (" Укажите произвольный символ. Q - признак конца работы. \n");

ch = getchar( );

printf ("Так! Вы указали %с!\n", ch);

if(ch != 'Q') more( );

}

more( );

{

main( );

}

Функция main( ) вызывает more(), а функция more() вызывает main()! После вызова функции main( ) ее выполнение начинается с самого начала; мы организовали цикл с взаимным вызовом.