рефераты

рефераты

 
 
рефераты рефераты

Меню

Реферат: Turbo C++ Programer`s guide рефераты

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

Объявления формальных параметров

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

int func(void) (*                          // аргументы отсутствуют

С++int func(T! t1, T2 t2, T3 t3=1)  (*

// три простых параметра,

// один из которых с аргументо

// по умолчанию

C++int func(T1* ptr1, T2& tref)   (*

// аргументы указатель и ссылк

int func(register int i) (*   // запрос регистра для аргумен

int func(char *str,...) (* /* один строковый аргумент ипеременное число прочих аргументов, либо фиксированное число аргументов с переменными типами */

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

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

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

В деклараторах формальных параметров могут использоваться модификаторы const и volatile.

Вызовы функций и преобразования аргументов

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

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

1. Модификаторы языка для определения функции должны соответствовать модификаторам, используемым в объявлении функции, при всех вызовах функции.

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

Если ранее не был объявлен прототип функции, Turbo C++ преобразует интегральные аргументы при вызове функции в соответствии с правилами интегрального расширения, описанными в разделе "Стандартные преобразования" на стр.41 оригинала. При наличии в контексте прототипа функции Turbo C++ преобразует данные аргументы к объявленным типам параметров, как при операции присвоения.

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

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

Важное замечание

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

Структуры

Инициализация структуры описана на стр.42 оригинала.

Структура - это производный тип данных, обычно представляющий собой определяемый пользователем набор именованных компонентов. Эти компоненты могут быть любого типа, как фундаментального, так и производного (с некоторыми описываемыми далее ограничениями), и располагаться в любой последовательности. Кроме того, компонент структуры может иметь тип битового поля, более нигде не разрешаемого. Тип струтуры в Turbo C++ позволяет обрабатывать сложные структуры данных так же легко, как и простые переменные.

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

Объявление структур выполняется при помощи ключевого слова struct. Например,

struct mystruct (* ... *); // mystruct - это тег структуры

...

struct mystruct s, *ps, arrs[10];

/* s имеет тип структуры mystruct; ps это указатель на тип struct mystruct */

Структуры без тегов и определения типов (typedef)

Структуры без компонентов и компоненты объединений при инициализации игнорируются.

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

struct (* ...*) s, *ps, arrs[10];  //структура без тега

При объявлении структуры, как с тегом, так и без него, можно создать typedef:

typedef struct mystruct (* ... *) MYSTRUCT;

MYSTRUCT s, *ps, arrs[10];                            // то же, что и

// struct mystruct s и т.д.

typedef struct (* ... *) YRSTRUCT; // тег отсутствует YRSTRUCT y, *yp, arry[20];

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

Объявления компонентов структуры

Список-объявления-компонентов вфигурных скобках объявляет типы и имена компонентов структуры при помощи синтаксиса декларатора, показанного в таблице 1.11 на стр.36 оригинала.

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

1. Тип компонента не может быть тот же, что и объявляемая в текущий момент структура:

struct mystruct (* mystruct s *) s1, s2;// недопустимо

Компонент структуры может являться указателем на объявляемую структуру, как в следующем примере:

struct mystruct (* mystruct *ps *) s1, s2; // так можно

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

В С++ ключевое слово struct может быть опущено.

2. Кроме С++, компонент структуры нигде не может иметь тип "функция, возвращающая ...", но тип "указатель на функцию, возвращающую ..." допустим. В С++ struct может иметь компоненты-функции.

Структуры и функции

Функция может иметь возвращаемое значение типа структуры или указателя структуры.

mystruct func1(void); // func1() возвращает структуру mystruct

*func29void); // func2() возвращает указатель структуры

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

void func1 (mystruct s);   // непосредственно

void func2 (mystruct *sptr);   // через указатель

void func3 (mystruct &sref); // по ссылке (только С++) Доступ к компоненту структуры

Доступ к компонентам структур и объединений выполняется операторами выбора . и ->. Предположим, что объект имеет тип структуры S, а sptr это указатель на S. Тогда, если m это идентификатор типа M, объявленного в S, то выражения s.m и sptr->m имеют тип M и представляют объект m - компонент структуры s. Выражение s->sptr является удобным синонимом (* sptr).m.

Операция . называется прямым селектором компонента структуры; операция -> называется косвенным селектором компонента (или указателем) структуры; например,

struct mystruct (*

int i;

char str[21];

double d;

*) s, *sptr=&s;

...

s.i = 3; // присвоению члему i структуры mystruct s sptr->d = 1.23; // присвоение компоненту d структуры mystruct s

Выражение s.m является именуемым значением (lvalue), если s это не именуемое значение и s не имеет тип массива. Выражение sptr->m является именуемым выражением, если m не имеет тип массива.

Если структура B содержит поле, тип которого есть структура A, то доступ к компонентам A выполняется через два одновременно задаваемых селектора компонента структуры:

struct A (*

int j;

double x;

*)

struct B (*

int i;

struct A a;

double d;

*) s, *sptr;

...

s.i = 3; // присвоение компоненту i структуры B s.a.j = 2; // присвоение компоненту j структуры A sptr->d = 1.23; // присвоение компоненту d структуры B (sptr->).x = 3.14 // присвоение компоненту x структуры A

Каждое объявление структуры вводит уникальный тип структуры, поэтому в

struct A (*

int i,j;

double d;

*) a, a1;

struct B (*

int i,j;

double d;

*) b;

объекты a и a1 оба имеют тип struct A, но объекты a и b имеют различные типы структуры. Структурам может выполняться присваивание только в том случае, если и исходная структура, и структура назначения имеют один и тот же тип:

a = a1;// так можно; тип один и тот же, поэтому может быть // выполнено покомпонентное присвоение структур

a = b;// так нельзя; разные компоненты

a.1 = b.1; a.j = b.j; a.d = b.d; // однако присвоение можно // выполнять на уровне компонентов структуры

Выравнивание по границе слова

Память распределяется структуре покомпонентно, слева-направо, от младшего к старшему адресу памяти. В следующем примере

struct mystruct (*

int i;

char str[2];

double d;

*) s;

объект s занимает достаточное количество памяти для размещения 2- байтового целочисленного значения, 21-байтовой строки и 8-байтового значения типа double. Формат данного объекта в памяти определяется опцией Turbo C++ выравнивания по границе слова. Когда эта опция выключена (по умолчанию), s будет занимать 31 байт непрерывно. Если же включить выравнивание по границе слова опцией -a компилятора (или в диалоговом поле Options \! Compiler \! Code Generation), то Turbo C++ заполняет структуры байтами таким образом, что структура была выравнена по следующим правилам:

1. Структура должна начинаться по границе слова (четный адрес).

2. Любой не-символьный элемент будет иметь четное смещение в байтах относительно начала структуры.

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

Если опция выравнивания включена, топриведенный пример структуры имел бы добавленный перед double байт, и весь объект в целом занимал бы 32 байта.

Пространство имен структур

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

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

goto s;

...

struct s (* // так можно; теги и имена меток находятся в разных // адресных пространствах

int s; // так можно; теги, имена меток и имена компонентов // дятся в разных адресных пространствах

float s;// так нельзя: повторение имени компонентов структур *) s; // так можно; пространства имен переменных различны // В С++ это допустимо только если s не имеет

// конструктора.

union s (* // так нельзя: повторение имен в пространстве тегов int s; // так можно: новое пространство компонентов float f;

*) f;                      // так можно: пространство имен переменных

struct t (*

int s; // так можно: следующее пространство имен компоненто

...

*) s;                      // так нельзя: повторение имен переменных

Неполные объявления

Указатель структуры типа А допустим в объявлении другой структуры В до объявления структуры А:

struct A;// неполное объявление struct B (* struct A *pa *);

struct A (* struct B *pb *);

Первое объявление А называется неполным, поскольку в этой точке отсутствует определение А. В данной ситуации неполное объявление допустимо, поскольку в объявлении В размер А необязателен. Битовые поля

Структура можетсодержать любые комбинации битовых полей с данными других типов.

Целочисленные компоненты типа signed или unsigned можно объявить битовыми полями шириной от 1 до 16 бит.  Ширина битового поля и его опциональный идентификатор задаются следующим образом:

спецификатор-типа <идентификатор-битового поля>:ширина;

где спецификатор-типа это char, unsigned char, int или unsigned int. Битовые поля располагаются с нижнего и кончая саршим битом слова. Выражение "ширина" должно быть задано и должно давать целочисленную константу со значением в диапазоне от 0 до 16.

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

struct mystruct (*

int i:2;

unsigned  j:5;

int  :4;

int k:1;

unsigned  m:4;

*) a, b, c;

создает следующее распределение памяти.

\!

\! 15\!

4 \! 3 \!

14\! 13\! 12\! 11\! 2 \! 1 \! 0 \! 10\! 9 \ 8 \! 7 \! 6 \! 5
\!

\! x \!

x \! x \!

x \! x \! x \! x \!

x \! x \! x \!

x \! x \ x \! x \! x \! x
--

\!<----

->\!<----

-------->\!<->\!<---

>\!

---- - - >\ <- - -- - -- -
\ m \! k \ не используется\! j \ i \!

Целочисленные поля хранятся в виде дополнения до двух, причем крайний левый бит побещается в MSB (наиболее значащий бит).Для битового поля типа Int (например, signed) MSB интерпретируется как знаковый бит. Битовое поле шириной 2, содержащее двоичное 11, будет, следовательно, в случае типа unsigned интерпретироватьсякак 3, а в случае Int как -1. В предыдущем примере допустимое выражение a.i = 6 поместит в a.i двоичное 10 = -2, не выдавая каких-либо предупреждений. Поле k типа signed int шириной 1 может содержать только значения -1 и 0, так как битовый шаблон 1 будет интерпретирован как -1.

Примечание

Битовые поля могут быть объявлены только в структурах, объединениях и классах. Доступ к ним выполняется теми жеселекторами компонентов (. и ->), что используются для доступа к компонентам других типов. Кроме того, битовые поля вызывают некоторые проблемы с созданием переносимых кодов, поскольку организация битов в байтах и байтов в словах зависит от конкретной машины.

Выражение &mystruct.x недопустимо, так как x это идентификатор битового поля, а никакой гарантии, что mystruct.x имеет адрес на границе байта, нет.

Объединения

Объединения соответствуют типам вариантных записей языков Pascal и Modula-2.

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

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40