
programmirovanie / ОПиАЯ_№3_6_пп_слайды
.doc4 Подпрограмма в СИ
Си-программа состоит из одной или нескольких функций – обычных(рассматриваются ниже), функций-членов дружественных функций и шаблонов функций.
Обычная функция подобна функции main . Ее объявление имеет вид:
[тип] f ([список формальных параметров])
{[декларативная часть;]
операторы;
}
Предложение объявления является
заголовком функции(до {}), а совокупность предложений в фигурных скобках – телом.
Встретив объявление функции, компилятор создает самостоятельную секцию кода программы.
На этом этапе компоновки она объединяется с другими функциями.
В заголовке функции слово тип задает тип возвращаемого функцией f значения – основной или типа указатель
(функция может возвращать указатель на любой тип, включая массивы и функции).
По умолчанию (тип не написан) результатом будет int-данное.
Каждая функция глобальна
(по умолчанию имени f назначается класс памяти extern’).
Внутренних функций в Си нет.
Имя f это особый тип указателя, называемого указателем на функцию. Его значение – адрес точки входа в функцию.
Список формальных параметров либо не содержит таковых(и тогда он пуст или включает слово void), либо состоит из разделенных запятой спецификаций параметров, каждая из которых представляет собой конструкцию вида
тип
v
,
где тип(i=1,2,…,n)
– тип параметра,
v
- его имя.
Формальным параметром может быть переменная основного и перечисляемого типов, типа указатель и массив, структура и объединение.
Тело функции – блок или
(реже) составной оператор.
Обязательным оператором тела является оператор возврата вида return выражение.
Он прекращает выполнение функции и передает значение выражения и управление в точку вызова.
Вызов функции
f([u,
u
,…,u
])
- это первичное выражение. Операция в нем обозначается круглыми скобками.
Операндами служат имя
функции(вычисляется как адрес) и
фактические параметры u(i=1,2,…,n).
Здесь любое u
-выражение, тип значения которого
основной, структура, перечисление,
объединение или указатель.
Формальные и фактические параметры нужно согласовать. Контроль соответствия числа и типа параметров компилятор выполнит только тогда, когда до первого обращения функции будет помещено либо ее объявление, либо прототип, т.е. опережающее объявление.
Прототип почти полностью совпадает с заголовком функции: первое отличие – присутствие точки и запятой в конце заголовка,
второе – необязательность имен формальных параметров.
Общепринятая практика – размещение прототипов функций и объявление внешних объектов (переменных, массивов и пр.) в заголовочном файле, подключаемом к тексту программы директивой
#include “имя файла.с”
Все параметры функции, за исключением параметров типа указатель и массив, передаются по значению (на это тратится и дополнительная память и время).
Т.к. функция будет работать с копиями фактических параметров, параметры-значения нельзя использовать для возврата результатов.
Обрабатывая вызов функции, компилятор вставляет в код программы последовательность команд, выполняющих следующие действия
1. Подсчитывается значение выражения
u
(i=1,2,…,n).
Его тип сравнивается с типом соответствующего формального параметра, заданным в прототипе функции.
Если они не совпадают, то либо производится преобразование типа, либо выдается диагностическое сообщение.
2. Компилятор в точке вызова размещает команды загрузки в стек значений фактических параметров, происходит замена формальных параметров на фактические: первый фактический параметр всегда соответствует первому формальному параметру, второй - второму и т.д.
3. Здесь же, в точке вызова, компилятор поместит команду вызов функции с возвратом.
В результате ее выполнения управление передается к точке входа в функцию, на первую ее команду. Код функции всегда содержит команду возврата. Она располагается на месте оператора return, а при его отсутствии – на месте последней фигурной скобки тела функции. ЕЕ выполнение возвращает управление и возможное значение в точку вызова. Память в стеке освобождается. На этом работа функции завершается.
#include <stdio.h>
float mmm(float x1,
float y1);
main()
{
…
Z=mmm(X,Y);
…
getch();
}
float mmm(float x1,float y1)
{
/* */
return(x1*y1);
}
Функция void
Если в заголовке функции указан тип void, функция явно не возвращает никакого значения. Неявно же любая функция может передать в вызывающую функцию результаты своей работы посредством указателей (вызов функции с передачей адресов переменных) и/или глобальных переменных (обмен данными через общую память).
В теле void-функции может содержаться сокращенный оператор возврата return. Он прерывает выполнение функции и передает управление к точке вызова. Т.к. на организацию возврата тратится несколько команд, использование void позволяет получить боле эффективный код программы. Если в качестве параметра используется указатель переменной нудно применить операцию разадресации * этой переменной для доступа и изменения ее значения.
#include <stdio.h>
float mmm1();
int X;
/*глобальные переменные*/
float Y,Z;
main()
{
printf("\n int X floatY");
printf("\n");
scanf("\n %d %f",&X,&Y);
printf("%d %f ",X,Y);
Z=mmm1();
printf("\n Z= %f ",Z);
getch();
}
float mmm1()
{
/* */
return (Y*Y);
}
#include <stdio.h>
void mmm2(int x1,float y1);
main()
{
int X;
/*локальные переменные*/
float Y,Z;
printf("\n ўўҐ¤ЁвҐ 楫 ¤Ґ©бв бЁ¬ў®« ¬ ббЁўЁ§ 3-е");
printf("\n");
scanf("\n %d %f",&X,&Y);
printf("X=%d Y=%f",X,Y);
mmm2(X,Y);
printf("\n Y= %f ",Y);
getch();
}
void mmm2(int x1,float y1)
{
/* */
x1=x1*x1;
y1=y1*y1;
printf("\n fun X=%d Y=%f",x1,y1);
}
#include <stdio.h>
void
mmm3(int x1,float *y1,float *z1);
main()
{
int X;
float Y,Z;
printf("\n vvod intX floatY");
printf("\n");
scanf("\n %d %f",&X,&Y);
printf("X=%d Y=%f",X,Y);
mmm3(X,&Y,&Z);
printf("\n Y= %f Z=%f ",Y,Z);
getch();
}
void mmm3(int x1,float *y1,float *z1)
{
/* */
*y1=x1+x1;
*z1=*y1*(*y1);
printf("\n fun Y=%f Z=%f",*y1,*z1);
}
Каковы значения переменных x и у в отмеченных точках.
void silly(int x) /*по значению*/
{int y;
y=x+2;
x=2*x;
}
main()
{int x,y;
x=10; y=11;
silly(x);
silly(y);
…
}
void silly(int *x) /*по ссылке*/
{int y;
y=*x+2;
x=2**x;
}
main()
{int x,y;
x=10; y=11;
silly(&x);
silly(&y);
…
}
#include <stdio.h>
void mmm(int x1[2], int *z1, float y[1]);
main()
{
int X[2],Z;
float Y[7];
printf("\n vvod intX floatY");
printf("\n");
X[0]=1;
X[1]=2;
Y[5]=125,5;
mmm(X, Z,&y[5]);
printf("\n Z=%d ",Z);
printf("\n x[1]=%d ",x[1]);
printf("\n y[5]=%f ",y[5]);
getch();
}
void mmm(int x1[2],int *z1, float yx[1])
{
/* */
*z1=x1[0]+x1[1];
printf("\n fun z1=%d",*z1);
printf("\n fun y[5]=%f",yz[0]);
}
Передаем параметр через командную строку
#include <GRAPHICS.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
main(int argc,char *argv[])
{
int i,j,i7;
char a[6],b[6];
if(argc==0) {printf("yk imja bx byx file"); exit(-1);}
printf("\n %s",argv[1]);
printf("\n %s ",argv[2]);
getch();
}
Из командной строки
fff_777.exe
S K