Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

chast1

.pdf
Скачиваний:
16
Добавлен:
10.06.2015
Размер:
499.82 Кб
Скачать

необходимо помнить, что на случай применениядинамических массивов распространяются все опасности из пункта 6.2.1 (одномерные массивы). в чпстности,хотя имя указателя играет роль динамического массива, оно, в отличии статического массива, это не указатель0констатнта,а указатель-переменная, следовательно ему можно присвоитьновое значение. Если это по неосторожности сделать, то адрес динамического массива может бытьбезвозвратно потерян и массив нельзя будет уничтожить операцией delete, а значит образуется мусор. Эти опасности распространяются и на многомерные динамические массивы. Важным достоинством динамических массивов то, что количество элементов массива можно задавать не константным выражением,а переменной.

int RAZM=3;//(4) int*t=new int[RAZM];//(5)

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

___________________________________________________________________________________

26Структуры - основные понятия.Допустимые варианты обращения к полям структуры.

_________________________________________________________________________________

До настоящего времени среди именованных типов данных языка с ++,мы рассматривали только базовые (простые) типы. Термин " именованный тип" предполагает наличие уникального имени типа (char,int,duable и.т.д.) , которые можно использовать при определении переменных этих типов.

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

Замечание.

именованный тип массива также можно объявить с++ используя спецификатор typedef(пункт 6.6 переименование и наименование типов(спецификатор typedef)). В то же время в с++ есть возможность объявить свои именованные структурно сложные типы, это:

-структуры -объединения -классы

Структуры и объединения унаследованы от языка с, но в с++ они являются упрощенными разновидностями классов.

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

Формат определения структуры, как типа данных struct<имя структуры>;//(1)

{

<type1><элемент1>;//(2) <type2><элемент2>;//(3)

...

<typeN><элемент N>;//(4) };

тип элементов структуры можетбыть как базовым так и производным типом с++.

Пример структуры, предназначенной для храненияадресных данных людей. struct address//(5)

{

char FIO[30];//(6) char region[20];//(7) char city[20];//(8) char street[30];//(9) int house;//(10) int flat;//(11)

};

Нужно понимать, что после определения структурыaddress,как типа, никакой объект не создается,т.е.не выделяется область памяти, в которой будут храниться значения.

Определение вида 5-11 означают только то, что могут быть созданы объекты, имеющие объявленную структуру.

Например,можем определить переменные для хранения собственно адресных данных. address men1 men2;//(12)

После обработки этого определения в памяти компьютера будут выделены две области памяти, имеющие имена men1 и men2, каждый объемом 108 байт.

При определении структуры задавать ее имя целесообразно (address),в том случае если это имя используется многократно.

Например Помимо определений из строки 12 нам нужны ещеи такие определения

address woman1,woman

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

Пример struct//(14) {-//- //(15=6)

...

-//- //(20=11)

}men3,group[21], *pmen;//(21)

здесь в целом определен безымянный структурныйтип и три переменные. -Переменная men3 ,имеющая структуру , объявленную в строчках 15-20

-Массив из 21 элемента,каждый из элементов имеет указанную структуру, т.е.это массив структур. -Указатель pmen, который может указывать на область памяти, в которой хранится значение заданной структуры. pmen может быть инициализирован:

pmen=&men3;//(22)

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

strcpy(men3.FIO(квалифицируемое имя),"Иванов И.И.");//(13)

Здесь применена стандартная функция strcpy, которая копирует символьный массив ( массив FIO), значение строковой константы и после константы добавляется '\0'(терминальный ноль), т.е. возникает строка в стиле с.

Если элемент структуры является поле массив, то к элементам этого массива обращаются как обычно по индексам.

пример int i=0;//(24)

while(men3.FIO[i] != '\0')//(25) sout<<men/FIO[i++];//(26) sout<<endl;//(27)

Цикл while последовательно выводит на монитор строку "Иванов и.и."

Пример обращения к целому полю. men3.house=10;//(28)

Если переменная сама является массивом,а его элементы это структуры,то обращение к отдельным элементам этих сложных элементов( структур) могут иметь такой вид:

пример

strcpy(group[3].FIO,"Иванов И.И." );//(29) group[3].FIO[10]='A';//(30)

group[3].house=11;//(31)

если объявлен указатель на структуру, то для обращения к отдельным полям структуры необходимо использовать операцию -> "выбор элементов по указателю".

Пример strcpy(pmen->FIO,"И.И.Иванов"//(32)

В результате в поле FIO структурной переменной men3 будет внесена строковая константа pmen->FIO[10]='A';//(33)

pmen->house=11;//(34)

Другой вариант работы с указателями на структуручерез операцию разыменования strcpy((*pmen).FIO,"Иванов И.И.");//(35)

(*pmen).FIO[10]='A';//(36) (*pmen).house=11;//(37)

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

pmen->house (*pmen)/house men3.house

_________________________________________________________________________________

Структуры сполями, имеющими тип стрктуры или указателя на структуру. Работа со структурной переменой,как с целостностью. Битовые поля. размещение элементов структурного типа в памяти ЭВМ.

________________________________________________________________________________

Поскольку тип структуры может быть производными сложным, рассмотрим этот вопрос специально.

Вчастности поле данной структуры может иметь тип другой, ранее определенной структуры. Из этого правила есть одно исключене: в структуру нельзя включать поле того же типа,что и определяемая структура.

Контрпример.(неправильно) struct rec

{int i; rec r;}

Вто же время допустимо определять внутри данной структуры поле,которое имеет тип укзателя на структуру определяемого типа, т.е. допустим такой вариант:

struct rec //(38) {int i;//(39) rec*prec;//(40)

более сложный вариант: определяется структура rec1, поле которой является другой структурой rec2 в которой тодной из полей относится к типу указатель на rec1. в этом случае необходимо использовать" упреждающеенеполное определение" структуры rec.

struct rec1;//(41)

Это упреждающее неполное определение. struct rec2{int i;rec1*a;};//(42)

struct rec1{duable x;rec2 b;};//(43)

Синтаксис языка с++ допускает неполное упреждающее определение структуры, поскольку определение указателя а на структуру rec1 не требует детальнойинформации об этой структуре.

Пример работы с переменной типа rec1 rec1 sA;//(44)

sA.b.i=77;//(45) sA.b.a=new rec1;//(46) sA.b.a->x=8.8;//(47)

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

address men4={"И.И.И.","МО","С.П.","пр.Кр.Ар",10,20};//(48)

Если определяется массив, элементы которого являются структурами,то при его инициализации выполняется также и правила инициализации массивов.

Для переменных одного и того же структурного типа, как для целостностей определена операция присваивания.

Например

men1=men4;//(49)

Врезультате значения из области памяти men4 будут скопированы в область памяти men1.

Всруктуры можно включать "битовые поля". Такие поля могут применяться в том случае,ксли на поле необходимо выделить объем памяти некраиный 1 байту. Это могут быть "поля - флажки" Т.е. однобитовые поля,в которых храняться либо 0,либо 1.

Основной аргумент в пользу применения таких полей - это экономия памяти,хотя реально экономия памяти существенно зависит от реализации компелятора.

Синтаксис определения битового поля.

<тип поля><имя поля>:<ширина поля в битах>;//(50)

В качестве типа разрешено указывать любой целыйтип.

Битовые поля могут быть только элементами объединений структур или классов, т.е. они не могут создаваться , как самостоятельные объекты программы. нельзя объявить указатель или ссылку на битовое поле, следовательно нельзя применить операцию взятия адреса(&)

Пример struct rbit //(51)

{int i;//(52) обычное целое поле signed bit1:2;//(53) битовое поле char bit2:1;//(54)

}S_bit;//(55)

В результате в поле S_rbit.bit1 можно хранить целые числа (0-3), а в поле S_rbit.bit2 (0-1) (чистый флажок) Рассмотрим вопрос о размещении элементов переменной структурного типа в памяти компьютера. Общим правилом является правило непрерывного распределения элементов структуры в выделенной области памяти в порядке перечисления полей в определении структуры. конкретная же реализация зависит от ревлизации компелятора и при этом часто выделение памяти на каждое поле осуществляется порциями, кратными длине слова данного компьютера (в 32-х разрядных машинах длина слова 4 байта).

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

struct{int i;char c[3];duable x;} S={10,'a','b','c',3.3};//(56)

тогда распределение даных, хранимых в переменной S будет таким, какой показан на рисунке 6.2

___________________________________________________________________________________

27.Объединение.

__________________________________________________________________________________

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

Часто синтаксическое отличие проявляется в том, что struct меняется на union. Содержательное отличие от структуры проявляетсяв размещении данных в памяти. Пример

Пусть даны определения именованных структуры иобъединения,а так же соответствующих переменных. struct rec //(1)подобно определению из строки 56

{int i;//(2) char[3];//(3)

double x;//(4) } S;//(5)

union uni //(6) {int i;//(7) char[3];//(8) double x;//(9) } U;//(10)

Размещение данные соответствующих переменнойS было показано на рисунке 6.2. Особенность же размещения в памяти U заключается в том,что все поля объединения имеют один и тот же адрес. При этом объем памяти выделяемой на переменнуюбудет определяться наиболее длинным словом (у нас это х). Это фактически означает что в каждый данный момент времени в переменной типа объединение можно хранить значение только одного поля. Сказанное иллюстрируется на рис.6.3.

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

Например

uni u1={10};//(11) в инициализаторе указано значение только поля i. В результате такой инициализации в байтах номерами А0-А3 будет храниться число 10, а в байтах А4-А7 будут храниться случайные значения, которые сформировались до выполнения строки. Внести значение в область памяти выделенную под переменную типа объединение можно с помощью имени любого типа.

Пример u1.x=3.33;//(12_ u1.i=20;//(13)

u1.c[0]='a'; u1.c[1]='b'; u1.c[2]='c';//(14)

Если эти операторы выполнить в указанном порядке то байты области памяти выделенные под переменную u1 будут заполнены так:

-в байтах с А0-А3 будет содержаться значение массива с[3], в байте А3 будет находиться фрагментбитового представления значения переменнойi (первыйбайт этого представления),в А4-А7 фрагменты битового представления значения переменной х (первые 4 байта). После этого хранящиеся значения,а точнее его побайтовое представление можно прочесть так жес помощью любого поля.

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

__________________________________________________________________________________

28.Перечисления.

__________________________________________________________________________________

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

Формат определения такого типа

enum[<имя типа>]{<список имен констант>};//(1)

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

Пример

enum ec{zero, one, two, three};//(2)здесь определили перечисляемый тип с именем ec, множество значений которого указано в {},причем по умолчанию константы zero,jne, two, three получают целочисленное значение начиная с 0.

В результате в программе будут допустимы такие действие: ec xen=three;//(3)

int i;//(4)

i=xen+two+43;//(5)

xen=xen+one;//(6)

При вычислении выражения правой части в строке 5 значение переменной xen и значение two автоматически преобразовываются к целому типу, т.к. слева стоит i-переменная целого типа. В тоже время неправильно так: xen=1, т.е. значение целого типа нельзя напрямую, т.е.без явного преобразования типа присвоить переменной перечисляемого типа.

Допустима так же явная инициализация всех или части констант:

enum ec1{one=1, two, three, eight=8, nine,ten};//(8) при таком определении константа one явно получает значение 1, следующим двум константам по умолчанию присваиваются последующие значения из натурально тяда,т.е. 2 и 3. Константа eight явно получает значение 8,соответственно следующим двум константам по умолчанию будут присвоены следующие значения из натурально ряда т.е. 9 и 10. Именованные константы перечисляемого типа можно использовать в качестве меток переключателя. Как правило константы и переменные перечисляемоготипа применяются тогда, когда их использование вместо явного использования числа делает программу наглядной.

__________________________________________________________________________________

29.Переименнование и наименованиетипов.Спецификатор typedef.

__________________________________________________________________________________

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

Формат применения этого спецификатора typedef<имя существующего типа><псевдоним>;//(1)

Например

typedef unsigned char byte;

В результате в программе допустимо следующее определение: byte k;//(3) определена переменная типа unsigned char

На семантическом уровне typedef фактически имеет 2 режима применения: 1 режим Переименование типа который уже имел ранее имя (см пример выше)

2 режим Придание имени какому-то типу который ранее получал имя.

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

typedef int proba[3][2];//(4)здесь объявленне месив как объект хранящийся в памяти,а тип массива и этому типу дано имя proba.

proba mpr;//(5)здесь определен конкретный двухмерный массив 3*2 с именем mpr, а его структура задается типом proba.

mpr[0][1]=123;//(6)пример работы с элементом массива.

ВС++ typedef не часто используют для предания имени типу массива.

Вразделе функции мы рассмотрим ситуацию когда второе решение применения спецификатора вполне уместно, а именно при работе с указателями на функции.

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

__________________________________________________________________________________

30.Понятие модульного программирования.Функции, как основа модульного программирования.

________________________________________________________________________________

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

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

если не принять необходимых мер, то количество ошибок будет увеличиваться не пропорционально объему текста,а быстрее О(n^3). Очевидно , что в этом случаи при достижении которого порогового объема программы написание правильной программы становится невозможным. Типичным примером преодоления таких трудностей, используемом не только в программировании, а почти в любом виде деятельности, является принцип декомпозиции задачи,т.е. разбитие ее на несколько относительно самостоятельных частей каждая из которых достаточна мала (обозрима) и поэтому человек способен удержать ее в памяти всю, как целостность.

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

В языке с++ модульный принцип построения программы реализуется благодаря :

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

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

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

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

2.Функции являются мощным средством построения библиотек алгоритма.

Вязыке с++ функции это основной конструктивныйэлемент любой программы, без которого построение программы вообще невозможно.

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

__________________________________________________________________________________

31.Определения и объявления функций.

__________________________________________________________________________________

Определение функций имеет вид [<модификатор>]<тип><имя функции> (<спецификация параметров>)//(1) { //(2)

<тело функции>//(3) } //(4)

Совокупность элементов, указанных в 1 строке называется заголовком функции. Затем идет тело фукции, которое является блоком, в частности в этом блоке может не быть вообще опператоров,но и в этом случае{}обязательны

Модификатор является необязательной частью заголовка. Здесь рассмотрим только модификатор static. Если функцию объявить с таким модификатором, то область её видимости будет только тот модуль гдеона определена. Иначе говоря явное указание static отменяетнеявное действие спецификатора extern. Спецификатор extern можно указать и явно но делать этого не надо.

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

<имя функции> - должно быть уникальным в глобальном пространстве имен.

<спецификация параметров> - это либо пусто, либо void,либо список спецификаций через (,). Вместо термина "спецификация параметров" частоиспользуют "Список формальных параметров",он может быть пустым но () обязательны.

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

Спецификация отдельного параметрадолжна иметь одну из следующих форм:

1)<тип><имя параметра>//(5)

2)<тип><имя параметра>=<умалчиваемое значение>//(5')

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

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

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

Особую роль в тебе функции играет оператор return. Формат его применения

return<выражение>;//(6)

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

В теле функции допускается размещать несколько return. Это логично например в случае задания в теле функции ветвящегося вычислительного процесса. Тогда в каждой ветви возможен свой return.

Работа алгоритма запрограммированного в теле функции прекращается в следующем случае: 1.Сработал оператор return.

2.Достигнута закрывающаяся скобка тела функции.

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

Объявление функции (её прототип) внешне совпадает с заголовком указанном в определении функции. При этом типы и порядок перечисления параметров должны быть точно такими как и в определении. Основное отличие заключается в том что после закрывающейся круглой скобки ставится (;). Умалчиваемое значение функции могут быть заданы не так как в определении, но при соблюдении общих правил работы с умалчивающими значениями. В спецификации параметров имена параметров могут быть другими и даже их можно опускать. Причина такова: компилятор вообще игнорирует имена параметров. Когда мы включаем в программу какой то заголовочный файл с помощьюдирективы include то тем самым мы добавляем объявление,т.е. прототипы нужный нам заголовочный файлов. Программист может создавать свои заголовочные файлы. Это имеет смысл делать когда у вас разработано много своих функций которые вы предполагаете использовать в разных программах или в разный файлах одной программы. Причем такие заголовочный файлы могут включать не толькопрототипы функции,но и объявления любых внешних операторов.

__________________________________________________________________________________

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

__________________________________________________________________________________

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

<имя функции>(<список аргументов>);//(1)

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

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

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

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

duable f1 (duable a, duable b,duable c,duable *r,duable & cosalf);//(2) прототип функции,которая будет определена позже.

void print (char*name, duable x)//(3) определение функции, предназначенной для вывода на экран вещественного значения с поясняющим текстом, функция ничего не возвращает,поэтому в теле функции return можно опустить.

{cout<<name<<" = "<<x<<endl;}//(4) тело функции name/ int main()//(5)

{ //(6) setlocale(LC_CTYPE,"Russian");//(7)

duable a1=2, b1=3, c1=4, S, cosalf1;//(8) определяем и сразу инициализируем длины сторон треугольника и определяем переменные для хранения площади треугольника (S) и косинуса угла,лежащего прогтив стороны a (cosalf1)

duable*r1=new duable;//(9) создаем динамическуюпамять для хранения радиуса вписанной в треугольник окружности.

S=f1(a1,b1,c1,r1,cosalf1);//(10) возвращает площадь треугольника. print("площадь треугольника",S);//(11)

print("радиус вписанной окружности",*r1);//(12) print("cos угла, лежащего против стороны а",cosalf1);//(13) _getch();//(14)

return0;//(15) } //(16)

Далее дадим определение функции f1

duable f1(duable a,duable b,duable c,duable*r,duable&cosalf)//(17) расчет площади треугольника по формуле Герона, радиус вписанной окружности и cos угла, лежащего против стороны а.

{duable pp, S;//(18) локально объявляем вспомогательные переменные. pp=(a+b+c)/2;//(19) полупериметр

*r=sqrt ((pp-a)*(pp-b)*(pp-c)/pp);//(20) расчет радиуса S=*r*pp;//(21) формула Герона cosalf=(b*b+c*c-a*a)/(2*b*c);//(22)

return S;//(23) } //(24)

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

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

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

-по значению, если в stec передается значение базового или производного типа.

- по адресу, если в stec передается значение адреса. Данный способ разделяется на две разновидности: передачу собственно по адресу и по ссылке.

Рассмотрим различия разных видов, опираясь на пример с функцией f1.

Передача параметров по значению.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]