Файл: Могилев А.В. Информатика.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 31.03.2021

Просмотров: 6823

Скачиваний: 51

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

 

326 

 
Завершает выполнение данной функции и передает управление вызывающей функции 

опе-

ратор return

; в

 главной функции main он же вызывает завершение выполнения всей программы. 

Оператор return может содержать любое выражение: 

 
return (<выражение>); 
 
Если  выражение  не  пусто,  то  вычисляется  его  значение,  которое  и  становится  значением 

данного вызова функции. 

Достижение  «конца»  функции  (правой  закрывающей  фигурной  скобки)  эквивалентно  вы-

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

Пример.

  Данная  программа  вычисляет  факториал,  если  число  меньше  8;  если  вводимое 

число больше или равно 8, то выводится сообщение «Очень большое число». 

 
Программа 100 

#include<stdio.h>  
main() 

int n, s() ; 
printf("Введите число "); 
scant("%d", &n) ; 
if (n<8) printf(=%d", s(n)) ; 
else printf("Очень большое число"); 

int s(x) /* определение функции с параметром */  
int x; 

int y,p=l; 
for (y=x; y>0; y- ) p*=y; 

return(p); /* Возвращает в основную программу значение р */ 

Результат работы программы: 
 
1. Введите число 4 
р=24 
2.Введите число 9 
Очень большое число 
 

Пример:

 предположим, что нужно вычислить x

2

 (для некоторого неотрицательного целого 

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

 

Программа 101

 

 
#include<stdio.h>  
main() 

int а, Ь, x, у, z; 
int odd() ; 
printf("\nВведите x, у через пробел: "); 
scanf("%d %d", &х, &у); а=х; Ь=у; z=l; 
while (b!=0) 
if (odd(b)) 
{ z=z*a; b- -;} 


background image

 

327 

else 
( a=a*a; b=b/2;} 
printf("\n%d", z); 

int odd(t)  
int t; 

return((t%2==0)? 0:1); 

Результат работы программы: 
 
Введите

 

x, у через пробел: 15 2  

225  
 
Если  функции  необходимо  вернуть  несколько  значений,  можно  использовать  два  различ-

ных приема: 

• применить глобальные переменные (в этом случае кроме изученных ранее характеристик 

переменных (имени, типа, значения), используется еще одна – класс памяти, см.ниже); 

•  применить  переменные  типа  «указатель»  в  качестве  аргументов  функции.  При  вызове 

функции информация о переменной может передаваться функции в двух видах. Если мы исполь-
зуем форму обращения  

 
function 1(х); 
 

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

 
function2(&x); 
 

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

 
function l(num)  
int num; 
 
Вторая форма обращения требует, чтобы определение функции включало в себя формаль-

ный аргумент, являющийся указателем на один из объектов соответствующего

 

типа:

 

 
function2(x)  
int *x; 
 
Обычно пользуются первой формой, если входное значение необходимо функции для неко-

торых вычислений или действий, и второй формой, если функция должна будет изменять значения 
переменных в вызывающей программе. Выше вторая форма вызова \же применялась при обраще-
нии к ф\нкции scanf(). Когда мы хотим ввести некоторое значение в переменную num, мы пишем 
scanf(''%d",&num).  Данная  функция  читает  значение,  затем,  используя  адрес,  который  ей  дается, 
помещает это значение в память. 

 
Пример:

 пусть необходимо поменять местами заданные значения переменных х и у. 

 

Программа 102

 

 
#include<stdio.h> 
main() 


background image

 

328 

int х, у; 
int interchange(); /* описание функции типа int */ 

x=l; y=3; 
printf("Имели... x=l y=3\n") ; 

interchange(&x, &y); /* обращение к функции (в данном случае пере-

даются адреса переменных) */ 

printf("Получили... x=%d y=%d", х, у); 


/* вызываемая функция */  
int interchange(u, v)  
int *u, *v; 

int p; 

p=*\i; *u=*v; *v=p; 

Результат работы программы: 
 
Имели х=1 у=3  
Получили х=3

 

у=1

 

 
В этой программе в вызове функции interchange(&x,&y) вместо передачи значений х и у мы 

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

Поскольку х и у целого типа, u и v являются указателями на переменные целого типа, и мы 

вводим следующее описание: 

 
int *u,*v; int p; 
 
Оператор  описания  используется  с  целью  резервирования  памяти.  Мы  хотим  поместить 

значение переменной х в переменную р, поэтому пишем: р=*u; Вспомните, что значение перемен-
ной u - это &х, поэтому переменная и ссылается на х. Это означает, что операция *u дает значение 
х, которое как раз нам и требуется. Мы не должны писать, например, так: 

 
р = u; /* неправильно */ 
 

поскольку при этом происходит запоминание адреса переменной

 

х, а не ее значения.

 

Аналогично, 

оператор *u = *v соответствует оператору х = у. 

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

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

1. Описать тип функции в ее определении: 
 
char pun(ch,n) /* функция возвращает символ */  
int n; 
char ch; 
 
2. Описать тип функции также в вызывающей программе. Описание функции должно быть 

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

 
main()  

char rch,pun(); 

 


background image

 

329 

6.6. КЛАССЫ ПАМЯТИ 

 

Помимо изученных ранее характеристик переменных (имени, типа, значения), в ряде случа-

ев оказывается важной еще одна - класс памяти. Класс памяти характеризует время существования 
и место хранения объекта в программе. 

Для обозначения класса памяти в языке Си используются следующие служебные слова: 
 
auto    

extern  

register  

static 

 
Автоматические  объекты  (auto)  являются  локальными  по  отношению  к  блоку  и  хранятся 

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

Автоматические объекты существуют только во время выполнения данного блока и теряют 

свои значения при выходе из него. При каждом вхождении в блок им присваиваются начальные 
значения, заданные в описании. Если начальные значения не заданы, то значения автоматических 
объектов при входе в блок не определены. До сих пор в этом параграфе рассматривались именно 
автоматические объекты. 

Объекты, описанные внутри блока с классом памяти register, называются регистровыми пе-

ременными. Они подчиняются всем правилам, касающимся автоматических переменных. Описа-
ние register указывает компилятору, что данная переменная будет часто использоваться. Когда это 
возможно, переменные, описанные как register, располагаются в машинных регистрах. Это приво-
дит к меньшим по размерам и более быстрым программам. 

Объекты,  описанные  внутри  функции  с  добавлением  класса  памяти  extern  или  описанные 

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

Внешние объекты делятся на внешние глобальные и внешние статические. 
Важно различать описание внешнего объекта и его определение. Описание указывает свой-

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

Например, появившиеся вне определения какой-либо функции строчки 
 
int max; 
char save[maxline]; 
 

определяют внешние переменные max и save, вызывают отведение для них места в памяти и слу-
жат в качестве описания для остальной части этого файла. В то

 

же

 

время строчки 

 
extern int max; 
extern char save[]; 
 

описывают в остальной части данного блока переменную max как int, a save как массив типа char 
(размеры которого указаны в другом месте), но не создают переменных и не отводят для них места 
в памяти. 

Во всех блоках, составляющих исходную программу, должно содержаться только одно оп-

ределение внешней переменной; другие блоки могут содержать описания extern для доступа к ней. 

 

Программа 103

 

 


background image

 

330 

#include<stdio.h>  
int i=0; 
/* Класс памяти переменной - внешний. Область действия переменной -любая про-
грамма, */ 
/* загружающаяся с данным файлом. Время существования 

i=0 -

 все время выпол-

нения программы. */ 
main()  

 

 

 

 

 

 

 

 

/* Блок уровня 1. */  

auto int i=l; 

/* В блоке 1 область действия 

i=l -

 функция main(). Время */ 

/* существования i=l - все время выполнения главной функции /*  
/* main(). /*  
printf("%d\n", i) ; 
/* Если две переменные имеют одно и то же имя, то по этому */  
/* имени обращаются к внутренней переменной, внешняя */  
/* непосредственно недоступна, поэтому после выполнения */  
/* блока 1 программа напечатает i=l. */  
{  

/* Блок уровня 2. */ 

int i=2; 
/* Класс памяти переменной i=2 - auto. Область */ 
/* действия i=2 - блок 2, время существования - время */ 
/* существования блока 2. блок 2, время существования -*/ 
/* время существования блока 2. */ 
printf("%d\n", i) ; 
/* Программа напечатает i=2. */ 

{  

/* Блок уровня 3. */ 
i+=l; printf("%d\n", i); 
/* Печатается самая внутренняя переменная с именем i,/*  
/* которая после выполнения операции данного блока */  
/* становится равной 3. */ 


/* Возвращение к блоку уровня 2. */ 
printf("%d\n", i) ; 
/* Опять печатается i=3. */ 

/* Возвращение к блоку уровня 1. */  
printf("%d", i) ; 

/* Переменная i=3 исчезает. Теперь самой внутренней переменной */  
/* с именем i будет i=l. */  

 
Программа 104 

#include<stdio.h>  
int a; 
main()  

extern int a; 
int P (); 

a=6; P(); 


int P() 

extern int a; 

printf("a=%d",a); 

Результат работы программы: 
 
a=6 
 
Областью  действия  статического  внешнего  объекта  является  модуль,  в  котором  описан