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

Turbo C++ Programer`s guide
Первый символ должен являться буквой или символом подчеркивания Тело функции, представляющее собой коды, выполняемые при вызове функции Выражение-приведения это пустой (null) указатель Е1 является указателем, а Е2 - константой типа пустого указателя Выражение-инремента выполняет приращения одного или нескольких цикловых счетчиков Вызвать конструктор тем же образом, что и обычную функцию, нельзя. Вызов деструктора допустим только с полностью квалифицированным именем Инициализатор конструктора (см. "инициализатор-конструктора" в описании синтаксиса декларатора класса в таблице Или 16). Ноль означает по умолчанию десятичную Мы будем обозначать все семейство математических сопроцессоров 80x87 термином "сопроцессор" В режиме эмуляции 80Х87 циклический переход в регистрах, а также ряд других особенностей 80х87 не поддерживается GrOk No error Нет ошибки Кроме того, обратите внимание на то, что функция прерывания выполняет выход с помощью команды IRET (возврата из прерывания) Как идентифицировать диагностические сообщения Что происходит, когда доступ к компоненту объекта типа объединения происходит при помощи компонента другого типа Печатаемые диагностические сообщения и поведение при завершении функции assert
668870
знаков
13
таблиц
0
изображений

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.

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

union myunion (* /* тег объединения = myunion */

int i;

double d;

char ch;

*) mu, *muptr=&mu;

идентификатор mu типа union myunion может служить для хранения 2-байтового значения int, 8-байтового значения double или 1-байтового char, но одновременно - только одного из этих значений.

Обе операции sizeof(union myunion) и sizeof (mu) возвращают значение 8, но когда mu содержит объект типа int, то 6 байт остаются неиспользованными (туда помещаются символы-заполнители), а когда mu сщдержит объект типа char - то 7 байт. Доступ к компонентам объединения выполняетсяпри помощи селекторов компонента структуры (. и ->), но требуется соблюдать осторожность:

mu.d = 4.016;

printf("mu.d = %f\n",mu.d);// порядок: на дисплее mu.d = 4.016

printf("mu.i = %f\n",mu.i);// забавный результат ! mu.ср = 'A';

printf("mu.ch = %c\n",mu.ch); // порядок: на дисплее mu.ch = A

printf("mu.d = %f\n",mu.d); // забавный результат ! muptr->i = 3; printf("mu.i = %d\n",mu.i); // порядок: на дисплее mu.i = 3

Второй оператор printf допустим, поскольку mu.i целочисленного типа. Однако, битовая комбинация в mu.i соответствует части ранее присвоенного значения типа double и не даст как правило полезной целочисленной интерпретации.

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

Объявления объединений

Общий синтаксисобъявления объединений во многом напоминает синтаксис объявления структур. Различия состоят в следующем:

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

2. С++ : В отличие от структур С++, объединения С++ не могут использовать спецификаторы класса доступа:public, private и protected. Все поля объединения имеют доступ private.

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

union local87 (*

int i;

double d;

*) a = (* 20*);

4. С++ : Объединение не может участвовать в иерархии класса. Оно не может являться производным от какого-либо класса или быть базовым классом. Объединение может иметь конструктор.

5. С++ : Анонимные объединения не могут иметь компоненты-функции.

Перечислимые данные

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

enum days (* sun, mon, tues, wed, thur, fri, sat *) anyday;

устанавливает уникальный интегральный тип, enum days, переменную anyday этого типа и набор нумераторов (sun,mon,...), которым соответствуют целочисленные константы.

Turbo C++ может хранить нумераторы в одном байте, если это позволяет диапазон значений нумераторов, когда выключена опция -b (по умолчанию она включена; это означает, что данные типа enum всегда int), но при использовании их в выражениях выполняется этих данных преобразования к типу int. Идентификаторы, используемые в списке нумераторов, неявно получают тип unsigned char или int, в зависимости от значений нумераторов. Если все значения могут быть представлены типом unsigned char, то это и будет типом каждого нумератора.

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

anyday = mon; // так можно

anyday = 1; // так нельзя, даже хотя mon == 1

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

enum days payday, holiday; // объявление двух переменных

С++ В С++ ключевое слово enum можно опустить, если в пределах данного контекста имя days не дублируется.

Как и в случае объявлений struct и union, если далее переменные данного типа enum не требуются, тег может быть опущен:

enum (* sun, mon, tues, wed, thur, fri, sat *) anyday;

/* анонимный тип enum */

Подробное описание констант перечислимого типа см. на стр. 17 оригинала.

Нумераторы, перечисленные внутри фигурных скобок, называются перечислимыми константами. Каждой из них назначается фиксированное целочисленное значение. При отсутствии явно заданных инициализаторов первый нумератор (sun) устанавливается в ноль, а каждый последующий нумератор имеет значение на единицу больше, чем предыдущий (mon = 1, tue = 2 и т.д.).

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

/* выражение инициализатора может включать в себя нумераторы, объявленные ранее */

enum coins (* penny = 1, tuppence, nickel = penny + 4, dime =10, quarter = nickel * nickel *) smallchange;

tuppence примет значение 2, nickel - значение 5, а quarter - значение 25.

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

Тип enum может участвовать во всех конструкциях,допускающих использование типов int.

enum days (* sun, mon, tues, wed, thur, fri, sat *) anyday;

enum days payday;

typedef enum days DAYS;

DAYS *daysptr; int i = tues; anyday = mon; // так можно

*daysptr = anyday; // так можно

mon = tues; // неверно: mon - это константа

Теги перечислимых типов разделяют пространство имен с тегами структур и объединений. Нумераторы разделяют пространство имен с обычными идентификаторами переменных:

int mon = 11;

(*

enum days (* sun, mon, tues, wed, thur, fri, sat *) anyday;

/* нумератор mon скрывает внешнее объявление int mon */ struct days (* int i, j;); // неверно: дублируется тег days

double sat; // неверно: переопределение sat

*)

mon = 12; // снова в контексте int mon

C++ В С++ нумераторы, объявленные в пределах класса,имеют контекст этого класса.

Выражения

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

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

Выражения Turbo C++ Таблица 1.19

первичное-выражение:

литерал

псевдо-переменная

(выражение)

this (только С++)

:: идентификатор (только С++)

:: имя-функции-операции (только С++)

имя

литерал:

целочисленная-константа

символьная-константа

константа-с-плавающей-точкой

строка

имя:

идентификатор:

имя-функции-операции (только С++)

имя-функции-преобразования (только С++)

квалифицированное-имя (только С++)

квалифицированное-имя: (только С++)

имя-класса :: идентификатор

имя-класса :: имя-функции-операции

имя-класса :: имя-функции-преобразования

имя-класса :: имя-класса

имя-класса :: - имя-класса

постфиксное-выражение:

первичное-выражение

постфиксное-выражение[выражение]

постфиксное-выражение (<список-выражений>)

постфиксное-выражение (<список-выражений>) (только С++) постфиксное-выражение . имя постфиксное-выражение -> имя постфиксное-выражение ++ постфиксное-выражение --

список-выражений:

выражение-присваивания

список-выражений , выражение-присваивания

унарное-выражение:

постфиксное-выражение

++ унарное-выражение

-- унарное-выражение

унарная-операция выражение-приведения

sizeof унарное-выражение

sizeof (имя-типа)

выражение-распределения (только С++)

выражение-отмены-распределения (только С++)

унарная-операция: одно из

& * + - тильда !

выражение-распределения: (только С++)

<::> new <местоположение> имя-ограниченного-типа <инициализатор

<::> new <местоположение> имя-типа <инициализатор>

местоположение: (только С++)

(список-выражений)

имя-ограниченного-типа: (только С++)

спецификатор-типа <декларатор-ограничения>

декларатор-ограничения: (только С++)

операция-указателя <декларатор ограничения>

декларатор-ограничения [<выражение>]

выражение-отмены-распределения: (только С++)

<::> delete выражение-приведения

<::> delete [выражение] выражение-приведения

выражение-приведения:

унарное-выражение

(имя-типа) выражение-приведения

выражение-типа-ссылки:

выражение-приведения

выражение-типа-ссылки .* выражение-приведения (только С ++) выражение-типа-ссылки -> выражение-приведения (только С+ +)

выражение-типа-умножения:

выражение-типа-ссылки

выражение-типа-умножения * выражение-типа-ссылки

выражение-типа-умножения / выражение-типа-ссылки

выражение-типа-умножения % выражение-типа-ссылки

выражение-типа-сложения:

выражение-типа-умножения

выражение-типа-сложения + выражение-типа-умножения

выражение-типа-сложения - выражение-типа-умножения

выражение-типа-сдвига:

выражение-типа-сложения

выражение-типа-сдвига << выражение-типа-сложения

выражение-типа-сдвига >> выражение-типа-сложения

выражение-отношения:

выражение-типа-сдвига

выражение-отношения < выражение-типа-сдвига

выражение-отношения > выражение-типа-сдвига

выражение-отношения <= выражение-типа-сдвига

выражение-отношения >= выражение-типа-сдвига

выражение-типа-равенства:

выражение-отношения

выражение-типа-равенства = выражение-отношения

выражение-типа-равенства != выражение-отношения

выражение-И:

выражение-типа-равенства

выражение-И & выражение-типа-равенства

выражение-исключающее-ИЛИ:

выражение-И

выражение-исключающее-ИЛИ выражение-логическое-И

выражение-включающее-ИЛИ:

выражение-исключающее-ИЛИ

выражение-включающее-ИЛИ \! выражение-исключающее-ИЛИ

выражение-логическое-И:

выражение-включающее-ИЛИ

выражение-логическое-И && выражение-включающее-ИЛИ

выражение-логическое-ИЛИ:

выражение-логическое-И

выражение-логическое-ИЛИ !! выражение-логическое-И

условное-выражение:

выражение-логическое-ИЛИ

выражение-логическое-ИЛИ ? выражение : условное-выражение

выражение-присвоения:

условное-выражение

унарное-выражение операция-присвоения выражение-присвоения

операция-присвоения: одно из

= *= /=%= += -=

<<= ??= &=^= \!=

выражение:

выражение-присвоения

выражение, выражение-присвоения

выражение-типа-константы:

условное-выражение

Стандартные преобразования подробно рассматриваются на стр.42 оригинала, в таблице 1.15.

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

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

Грамматические правила, приведенные в таблице 1.19, на стр. 74 оригинала, полностью определяют приоритеты и ассоциативность операций. Кратко эта информация сведена в таблице

1.20. Существует пятнадцать категорийприоритетов, некоторые из которых содержат только одну операцию. Операции, относящиеся к одной и той же категории, имеют одинаковый приоритет выполнения. Каждой категории соответствует собственное правило ассоциативности: слева-направо или справа-налево. При отсутствии в выражении круглых скобок эти правила используются для разрешения группировки выражения с операциями равного приоритета.

Ассоциативность и приоритеты операций Turbo C++ Tаблица 1.20

Операции Ассоциативность

() [] -> :: . Слева-направо

! тильда - ++ -- & * Справа-налево

sizeof new delete .* ->* / % Слева-направо

+ - Слева-направо

<< >> Слева-направо

< <= > >= Слева-направо

& Слева-направо

^ Слева-направо

\! Слева-направо

&& Слева-направо

\!\! Слева-направо

?:условное выражение Справа-налево

= += /= %= += -= Справа-налево

&= ^= \!= , Слева-направо

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

Выражения и Turbo C++

С++ позволяет перегрузку некоторых стандартных операций С, как описано начиная со стр.125 оригинала. Перегруженной называется такая операция, которая применительно к выражениям типа класса ведет себя некоторым специальным образом. Например, оператор отношения == может быть определен в классе complex для проверки равенства двух комплексныхчисел, причем действие его для типов данных других классов остается прежним. Перегруженный оператор реализуется как функция; эта функция определяет тип операнда, именующее выражение (lvalue) и последовательность вычислений, устанавливаемая при использовании перегруженного оператора. Однако, перегрузка не может изменять приоритеты операций. Аналогичным образом, С++ позволяет выполнять определяемые пользователем преобразования между объектами класса и фундаментальными типами. Учтите, что некоторые правила относительно операций и преобразований, обсуждаемые в данном разделе, неприменимы к выражениям в С++.

Последовательность вычислений

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

i = v[i++]; // i неопределено

Значение i зависит от того, выполняется ли инкрементирование до или после присвоения. Аналогичным образом,

int total = 0;

sum = [total = 3] + (++total);// sum = 4 или sum = 7 ??

имеет неоднозначность идентификаторов sum и total. Решение состоит в том, чтобы упростить выражение при помощи временной переменной:

int temp, temp = 0;

temp = ++total;

sum = (total = 3) + temp;

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

sum = (i = 3, i++, i++); // так можно: sum = 4, i = 5

Каждое под-выражение или выражение с запятыми вычисляется слева-направо, и все выражение в целом вычисляется понаправлению к самому правому значению.

Turbo C++ перегруппирует выражения, реорганизовывая ассоциативные и коммутативные операции независимо от наличия круглых скобок, с тем, чтобы получить эффективно компилируемое выражение; реорганизация выражения ни в коем случае не влияет на результатвычисления выражения.

Круглые скобки можно использовать для того, чтобы принудительно задать порядок вычислений в выражении. Например, если имеются переменные a, b, c и f, то выражение f=a+(b+c) вызывает сначала вычисление (b+c), а затем уже сложение результата с a.

Ошибки и переполнения

Во время вычисления выражения Turbo C++ может встретить многие проблематичные ситуации, как то деление на ноль или получение значений с плавающей точкой, выходящих за пределы допустимого диапазона. Переполнение целочисленных значений игнорируется (С использует арифметические действия по модулю 2 в n-разрядных регистрах), однако ошибки, обнаруживаемые математическими библиотечными функциями, могут обрабатываться стандартными или определяемыми пользователем подпрограммами. См. matherr и signal в Справочнике по Библиотеке.

- 76 -

Семантика операций

Описанные здесь операции Turbo C++ являются операциями стандарта ANSI C.

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

Если операция перегружена, то приводимые здесь сведениядля нее недействительны.Таблица 1.19 на стр.74 оригинала приводит синтаксис для всех операций и выражений с операциями.

Постфиксные и префиксные операции

Шесть постфиксных операций [] () . -> ++и -- используются для построения постфиксных выражений, показанных в таблице синтаксиса выражений (таблица 1.19). Операции инкремента и декремента (++ и --) также являются префиксными и унарными операциями;они обсуждаются, начиная со стр.79 оригинала.

Операция индексации массива [] --------------------------

В выражении

постфиксное-выражение [выражение]

в С, но не обязательно в С++, выражение выраж1[выраж2] определяется как

*((выраж1) + (выраж2))

где либо выраж1 это указатель, а выраж2 это целочисленное значение, либо выраж1 это это целочисленное значение, а выраж1 это указатель. (Каждый из пунктуаторов [], * и + может быть перегружен в С++).

Операция вызова функции ()

Выражение

постфиксное-выражение(<список-аргументов-выражения>)

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

Операция задания компонента структуры/объединения . (точка)

В выражении

постфиксное-выражение . идетификатор

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

Именующие выражения определяются на стр.28 оригинала.

Операция указателя структуры/объединения ->

В выражении

постфиксное-выражение -> идентификатор

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

Операция постфиксного инкремента ++

В выражении

постфиксное-выражение++

операндом является постфиксное выражение:

оно должно быть скалярного типа (арифметического или типа указателя) и должно являться модифицируемым именующим выражением (более подробная информация об именующих выражениях приводится на стр.28 оригинала.) Постфикс ++ также называют операцией постинкремента. Значением всего выражения является значение постфиксного выражения до выполнения инкремента. После вычисления постфиксного выражения операнд инкрементируется на 1.

Величина инкремента зависит от типа операнда. Значения типа указателя вычисляются по правилам арифметических действий с указателями.

Постфиксная операция декремента --

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

Операции инкремента и декремента

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

Операция префиксного инкремента ++

В выражении

++ унарное-выражение

операндом является унарное выражение:

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

Префиксная операция декремента --

Префиксная операция декремента, также известная как предекремент, имеет следующий синтаксис:

--унарное-выражение

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

Унарные операции

Существует шесть унарных операций (кроме ++ и --): . * + - тильда и !. Их синтаксис:

унарная-операция выражение-приведения

выражение-приведения:

унарное-выражение

(имя-типа) выражение-приведения

Операция адресации &

Символ & также используется в С++ для задания ссылочных типов данных. См. стр.98 оригинала.

Операции& и * (операция * описана в следующем разделе) используются совместно в качестве операций установки ссылки и ображения по ссылке (разыменования). В выражении

& выражение-приведения

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

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

Рассмотрим следующий фрагмент:

type t1 =1, t2 = 2;

type *ptr = &t1; // инициализированный указатель

*ptr = t2; // тот же эффект, что и t1 = t2

Отметим, что type *ptr = &t1 обрабатывается как

T *ptr; ptr = &t1;

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

Операция обращения по ссылке *

В выражении

* выражение-приведения

операнд выражение-приведения должен иметь тип "указатель на type", где type это любой тип. Результатом обращения по ссылке имееттип type.Если операнд имеет тип "указатель функции", то результатом будет являться обозначение функции; если операндом является указатель на объект, то результатом будет именующее выражение, обозначающее данный объект. В следующих ситуациях результат обращения по ссылке неопределен:


Информация о работе «Turbo C++ Programer`s guide»
Раздел: Информатика, программирование
Количество знаков с пробелами: 668870
Количество таблиц: 13
Количество изображений: 0

Похожие работы

Скачать
14945
0
7

... к сожалению, обратное утверждение не верно. C++ Builder содержит инструменты, которые при помощи drag-and-drop действительно делают разработку визуальной, упрощает программирование благодаря встроенному WYSIWYG - редактору интерфейса и пр. Delphi — язык программирования, который используется в одноимённой среде разработки. Сначала язык назывался Object Pascal. Начиная со среды разработки Delphi ...

Скачать
225728
6
0

... ориентированы на 32 разрядные шинные архитектуры компьютеров с процессорами 80386, 80486 или Pentium. Фирма Novell также подготовила варианты сетевой ОС NetWare, предназначенные для работы под управлением многозадачных, многопользовательских операционных систем OS/2 и UNIX. Версию 3.12 ОС NetWare можно приобрести для 20, 100 или 250 пользователей, а версия 4.0 имеет возможность поддержки до 1000 ...

Скачать
49224
0
9

... завдання поширюється на розробку системи обліку зареєстрованих автомобілів в ДАІ, призначеної для збору, зберігання, а також полегшення для доступу та використання інформації. Програма з обліку зареєстрованих автомобілів в ДАІ, представляє собою, перехід від паперових носіїв інформації до електронних. Система обліку зареєстрованих автомобілів значно допоможе працівникам ДАІ з обліку, аналізу та ...

Скачать
132529
1
5

... меньше времени и ответ клиенту агентство может дать уже в день подачи заявки. Каждая турфирма разрабатывает индивидуальный образец листа бронирования. Согласно Федеральному Закону «Об основах туристской деятельности в Российской Федерации» (гл. IV, ст. 9) – это конкретный заказ туриста или лица, уполномоченного представлять группу туристов, туроператору на формирование туристского продукта. ...

0 комментариев


Наверх