- •ЗАМЕЧАНИЕ <...> в описании правил записи (формата) конструкций языка означают понятие языка, в программе не записываются.
- •Пример
- •Формат
- •Значение
- •Содержание
- •Формат
- •if ( <выражение> )
- •Форма представления одного данного
- •Ввод двумерного массива
- •Вопрос? А как же передать результаты работы в вызывающую процедуру, если реально можно передать только одно значение?
- •Вызывающая
- •Вызываемая
- •ВЫЧИСЛЕНИЕ КВАДРАТИЧНОЙ ФОРМЫ
Существует два вида процедур: ПОДПРОГРАММЫ и ФУНКЦИИ. Отличие подпрограмм от функций – первые не возвращают значения в основную программу.
ПОБОЧНЫЙ ЭФФЕКТ. В Си формально определены только ФУНКЦИИ.
Связь между функциями осуществляется через входные аргументы, возвращаемые значения и внешние переменные.
Схема обмена данными между процедурами
Возвращаемое значение
|
|
Входные аргументы |
|
|
|
|
|
|
Вызываемая |
||
Вызывающая |
|
|
|||
|
|
Фактические |
|
Формальные параметры |
|
|
|
параметры |
|
|
|
Результаты
Возвращаемое значение функции разумно считать специфическим выходным параметром.
Формат ОПИСАНИЯ функции
[<тип_функции>] <имя_функции> ( [<описания_формальных_параметров>] ) <блок>
Если <тип_функции> отсутствует, то компилятор по умолчанию подставляет int. ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ. Если возвращаемое значение имеет тип не int, то указание типа в заголовке функции ОБЯЗАТЕЛЬНО.
Оператор return: Остановимся поподробнее на зарезервированном слове return. После него функция перестает выполняться и возвращает управление вызвавшей ее функции, передав значение, указанное после return, как результат. Слов return в функции может быть несколько, но хотя бы одно должно присутствовать обязательно. Исключение – когда функция имеет тип возвращаемого значения VOID. В этом случае слово return в функции может и отсутствовать, если оно есть, то оно не должно передавать что-либо в качестве результата. В этом случае слово записывается так: return ;
floatmin_fun (float x[], int n) {
int i, j; |
// Локальные переменные функции |
float min_value; |
|
................ |
|
return (min_value) |
} |
Да, и еще: локальные переменные функции существуют только во время выполнения этой функции. Они создаются всякий раз при входе в функцию и уничтожаются всякий раз при выходе из нее.
ПОДПРОГРАММА – это функция, не возвращающая значения. Ключевое слово <типа_функции> void.
void <имя_функции> ([<описания_формальных_параметров>]) <блок>
39
Тип void: Ключевое слово void используется для нейтрализации значения объекта, например, для определения функции не возвращающей никаких значений.
Пример:
void putmsg ( void ) { printf("Hello, world!\n");
}/* End putmsg */
Для ОБРАЩЕНИЯ к функции используется выражение с операцией “круглые
скобки”:
Обозначение_функции ( список_фактических_параметров ) ;
Операндами |
операции |
() |
служат |
Обозначение_функции |
и |
спи- |
|
сок_фактических_параметров. |
|
|
|
|
|
|
|
Наиболее естественное и понятное Обозначение_функции – это ее имя. Кроме того, |
|
||||||
функцию можно обозначить, разыменовав указатель на нее. |
|
|
|
||||
Сторонники Паскаля! Обратите внимание на разницу между mufunc и myfunc(). |
my |
myfunc ;
– то ошибки компиляции не будет (в выражениях допускается отсутствие операторов), но ничего не произойдет – для того, чтобы вызвать функцию, необходимо подействовать на нее оператором вызова функции ( ).
Список фактических параметров, называемых аргументами, – это список выражений, количество которых равно числу формальных параметров функции (исключение составляют функции с переменным количеством параметров). Соответствие между фактическими и формальными параметрами устанавливается по их взаимному расположению в списках. Порядок вычисления значений фактических параметров (слева направо или справа на лево) стандарт языка СИ не определяет.
Между формальными и фактическими параметрами должно быть соответствие по типам. Лучше всего, когда тип фактического параметра совпадает с типом формального параметра. В противном случае компилятор автоматически добавляет команды преобразования типов, что возможно только в том случае, если такое приведение типов допустимо.
В языке Си нет предопределенных функций. Каждая используемая функция должна быть где-то ОПРЕДЕЛЕНА (ОБЪЯВЛЕНА) до ее использования. Поскольку все функции могут транслироваться автономно, то в вызывающей процедуре необходимо ОПРЕДЕЛЕНИЕ вида (прототип функции):
(<тип_возвращаемого_значения>)<имя_функции>
( [ описание_параметров] ); Без него возвращаемое значение функции будет интерпретироваться как типа int и
возможна ошибка. Поэтому подпрограмма не описывается. Здесь возможны два варианта:
1. Если Вы используете встроенные функции среды Си, то самому писать многие требуемые функции (ввод-вывод, подключение файлов, математические функции и т.д.) каждый раз несколько скучно К счастью, Си снабжен библиотекой, содержащей в себе множество разнообразных функций. Для того, чтобы использовать ее, подключите к вашей программе требуемый ЗАГЛОВОЧНЫЙ ФАЙЛ (он имеет расширение .h) к вашей программе следующей строкой:
40
#include <Имя_заголовочного_файла>
На место этой строки в программу при компиляции будет подставлено содержание указанного файла.
2. Если Вы создали личную функцию, отличную от стандартных функций языка Си, то перед ее вызовом она обязательно должна быть объявлена:
Например, пусть определена функция с прототипом: int g ( int x, long y );
Далее в программе использован вызов : double m;
rez = g ( 3.0+m, 6.4e+2 );
Оба фактических параметра в этом вызове имеют тип double. Компилятор, ориентируясь на прототип функции, автоматически предусмотрит такие преобразования:
(int) rez = g ( (int)(3.0+m), (long)(6.4e+2) )
Пример (функция): |
|
void main( ) { |
|
double max (double, double ) |
// Прототип функции |
… |
|
max_value = max (cos(x), sin(x)); |
// Обращение к функции |
… } |
|
double max (double a, double b ) // Описание функции
{double y;
if ( a > b ) |
y = a; |
else |
y=b; |
return y; |
} |
Пример (подпрограмма):
/* Умножение матрицы на вектор */ matrix(a, b, c, m, n);
void matrix ( double p[10][10], /* Исходная матрица */
double q[10], |
/* Исходный вектор */ |
double s[10], |
/* Вектор–результат */ |
int l, |
/* Число строк */ |
int k) |
/* Число столбцов */ |
{ int i, j; |
|
for ( i=0; i<l; i++ ) { for ( s[i]=j=0; j<k; j++ ) { s[i] += p[i][j]*q[j]; } }
}/* End matrix */
В каждой программе должна быть процедура, которой передает управление ОС и которая остается активной в течение всей работы программы. Эта процедура называется ГЛАВНОЙ и имеет заголовок вида
int main([<параметры>]) <блок>
О параметрах пока умолчим, поэтому обычно имеем
41