Рубрики: КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

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

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

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

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

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

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

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

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

Символ & также используется в С++ для задания ссылочных
типов данных. См. стр.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.

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

В выражении

— 79 —

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

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

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

Унарная операция плюс +

В выражении

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

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

Унврная операция минус —

В выражении

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

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

Операция поразрядного дополнения (тильда)

В выражении

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

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

Операция логического отрицания !

В выражении

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

операнд выражение-приведения должен быть скалярного ти-
па. Результат иммет тип int и представляет собой логическое
отрицание операнда: 0 при ненулевом операнде и 1 в случае
нулевого операнда. Выражение !E эквивалентно выражению (0 ==
Е).
Операция sizeof

Существует два раздельных способа использования опера-
ции sizeof:

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

— 80 —

Размер выделяемой для каждого типа памяти зависит от
конкретной машины.

В обоихсучаяхрезультат представляет собой целочисленную
константу, выражающую размер в байтах областипамяти, занима-
емой операндом (определяемый за некоторыми исключениями ти-
пом операнда). В первом случае тип выражения операнда опре-
деляется без расчета выражения (и следовательно, без
побочных эффектов). Если операнд имеет тип char (signed или
unsigned), то операция sizeof дает в результате1. Если опе-
ранд не является параметром и имеет тип масива, то результат
представляет собой общее количество байтов в массиве (други-
ми словами, имя массива не преобразовавается к типу указате-
ля). Число элементов массива равно sizeof массив/sizeof мас-
сив[0].
Если операнд является параметром, объявленным как
массив или функция, sizeof дает размер указателя. Примени-
тельно к структурам и объединениям sizeof дает общее число
байтов, включающее любые символы-заполнители.

Целочисленный тип результата операцииsizeof называется
size_t, определенный как unsigned int в stddef.h.

Можно использовать sizeof в директивах препроцессора;
это особенность Turbo C++.

C++: В С++ sizeof(тип класса), где тип класса является
производным от какого-либо базового класса, возвращает раз-
мер базового класса.

Операции типа умножения

Существует три операции типа умножения: * / и %. Син-
таксис этих операций следующий:

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

Операнды операций * (умножения) и / (деления) должны
быть арифметического типа. Операнды операции % (деление по
модулю,или остаток) должны быть интегрального типа. С опе-
рандами выполняются обычные арифметические преобразования
(см. стр.41 оригинала).
Результатом выполнения операции (операнд1 * операнд2)
является произведение двух операндов. Результатами операций
(операнд1 / операнд2) и (операнд1 % операнд2) являются част-
ное и остаток от деления, соответственно, где операнд1 де-
лится на операнд2, при условии, что операнд2 не равен нулю.
Использование операций / и % с нулевым делителем дает ошиб-
ку.

Если операнд1 и операнд2 имеют целочисленный тип, а
частное не является целым, то результаты операции следующие:

1. Если операнд1 и операнд2 имеют одинаковый знак, то
операнд1/ операнд2 есть наибольшее целое, меньшее чем истин-
ное частное, а операнд1 % операнд2 имеет тот же знак, что и
операнд1.

2. Если операнд1 и операнд2 имеют разные знаки, то опе-
ранд1/ операнд2 есть наименьшее целое, большее чем истинное-
частное, а операнд1 % операнд2 имеет тот же знак, что и опе-
ранд1.

Страницы: 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

типа данных char диапазоне (от 0 до 0xff для Turbo C++).
Большие значения ведутк появлению ошибки компиляции «Numeric
constant too large» («числовая константа слишком велика»).
Например, восьмеричное число \777 больше максимально допус-
тимого значения \377, и вызовет генерирование ошибки. Первое
же не-восьмеричноеили не-шестнадцатиричное значение, встре-
ченное в восьмеричнойили шестнадцатиричной управляющей пос-

— 17 —
ледовательности, означает конец данной последовательности.

В исходной версии Turbo C допускалось только три цифры
шестнадцатиричной управляющей последовательности. Новые пра-
вила ANSI C, реализованные в Turbo C версии 2.0 и TurboC++,
могут вызвать проблемы со старыми кодами, предполагающими
преобразование только первых трех символов. Например, при
использовании версии Turbo C 1.x для определения строки со
звуковым сигналом (код ASCII 7), после которого следуют чис-
ловые символы, программист может написать:

printf(«\x0072.1Простая операционная система»);

Предполагается, что эта строка будет интерпретирована
как \x007 и «2.1Простая операционная система». Однако, Turbo
C++ (и TurboC версии 2.0) компилируют ее как шестнадцатирич-
ное число \x0072 и литеральную строку «.1Простая операцион-
ная система».

Чтобы избежать этих проблем, перепишитеваш код следую-
щим образом:

printf(«\x007» «2.1Простая операционная система»);

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

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

Управляющие последовательности Turbo C++ Таблица 1.7
————————————————————
Последовательность Значение СимволыВыполняемая функция
————————————————————
\a 0x07BELЗвуковой сигнал
\b 0x08BSЗабой
\f 0x0CFFПеревод бланка
\n 0x0ALFНовая строка (перевод строки)
\r 0x0DCRВозврат каретки
\t 0x09HTТабуляция (горизонтальная)
\v 0x0BVTВертикальная табуляция
\\ 0x5c\Обратная наклонная черта

Для фактического представления символа ASCII «обратная
наклонная черта», используемого например в команде DOS PATH,
следует записывать ее как \\.

\’ 0x27 ‘ Одинарная кавычка (апостроф)
\» 0x22 » Двойная кавычка
\? 0x3F ? Вопросительный знак
\OлюбыеO = строка до трех восьми-
ричных цифр
\xH любыеH = строка шестнадцатирич-
ных цифр
\XH любыеH = строка шестнадцатирич-
ных цифр
————————————————————

Специальные двух-символьные константы Turbo C++

Turbo C++ поддерживает также двух-символьные константы
(например, ‘An’, ‘\n\t’ и ‘\007\007’). Эти константы предс-

— 18 —
тавлены 16-битовыми значениями типаInt, где первый символ
расположен в младшем байте, а второй символ — в старшем бай-
те. Эти константы не могут быть перенесены на другие компи-
ляторы C.

Символьные константы со знаком и без знака

В C одно-символьные константы, такие как ‘A’, ‘\t’ и ‘\
007’, такжепредставлены 16-битовыми значениями типа Int. В
этом случае происходит расширение младшего байта в старший
байт по знаку; такимобразом, еслизначение превышает 127 (ос-
нование 10), то старший байт устанавливается равным -1
(=0xFF). Это свойство можно отменить, объявив, что по умол-
чанию тип char является unsigned (при помощи опции -R TCC,
либо выбором в меню Options \! Compiler \! CodeGeneration
опцию Unsigned Characters), чтоприведет к обнулению старшего
байта независимо от значения младшего байта.

Широкие символьные константы (только C)

Символьная константа, которой предшествует L, называет-
ся широкой символьнойконстантой и имеет тип данных wchar_t
(интегральный тип, определяемый в stdef.h). Например,

x = L ‘AB’;

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

Константа с плавающей точкой состоит из шести частей:

— десятичное целое
— десятичная точка
— десятичное дробное
— e или E и целочисленная экспонента со знаком (опционально)
— суффикс типа: f или F, либо l или L (опционально)

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

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

Примеры:
————————————-
Константа Значение
————————————-
6
23.45e6 23.45 x 10

.0 0

0. 0
0
1. 1.0 x 10 = 1.0

-1.23 -1.23
-5
2e-5 2.0 x 10
10
3E+10 3.0 x 10

— 19 —
34
.09E34 0.09 x 10
————————————-

Константы с плавающей точкой — типы данных

При отсутствии каких-либо суффиксов константы с плаваю-
щей точкой имеют тип данных double. Однако, вы можете прис-
воить константе с плавающей точкой тип данных float, добавив
к ней суффикс f или F. Аналогичным образом, суффиксl илиL
присвоит константе тип данных long double. В следующей таб-
лице показаны диапазоны значений, которые могут принимать
типы данных float, double и long double.

Размеры и диапазоны
констант с плавающей точкой Turbo C++ Таблица 1.8
————————————————————
Тип Размер (в битах) Диапазон значений
————————————————————
-38 38
float 32 3.4 x 10 до 3.4 x 10
-308 308
double 64 1.7 x 10 до 1.7 x 10
-4932 4932
long double 80 3.4 x 10 до 1.1 x 10
————————————————————
Перечислимые константы

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

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

enum team (* giants, cubs, dodgers *);

giants, cubs и dodgers это перечислимые константы типа
team, которые могут быть назначены любым переменным типа
team или любой другой переменной целочисленного типа. Значе-
ния, принимаемые перечислимыми константами,

giants = 0, cubs = 1, dodgers = 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

С учетом этого, следующие операторы являются недопустимыми:

pi= 3.0; /* присвоение значения константе */
i= maxint++; /* инкремент константы */
str = «Hi, there!»; /* установка указателя str на
что-то еще

Однако, отметим, что вызов функции strcpy(str,»Hi,
there!») является допустимым, поскольку он выполняет посим-
вольное копирование из строкового литерала «Hi, there!» в
адрес памяти, указываемый str.

В С++ const также «скрывает» объект const и предотвра-
щает внешнюю компоновку. При необходимости нужно использо-
вать extern const. Указатель на const не может быть присвоен

— 49 —
указателю на неconst (в противном случае значению const мог-
ло было быть выполнено присвоение при помощи указателя на не
-const.) Например,

char *str3 = str2 /* запрещено */

Модификатор функции прерывания interrupt

Модификатор interrupt специфичен для Turbo C++. Функции
прерывания предназначены для работы с векторами прерывания
8086/8088. Turbo C++ компилирует функцию interrupt с допол-
нительным кодом входа и выхода, таким образом, чтобы сохра-
нялись регистры AX, BX, CX, DX, SI, DI, ES иDS. Прочие ре-
гистры (BP, SP, SS, CS и IP) сохраняются как часть
вызывающей последовательности С или как часть самого обра-
ботчикапрерываний. Для возвратафункция использует команду
Iret, поэтому функция можетслужить для обслуживания аппарат-
ных илипрограммных прерываний. Ниже показан пример типичного
определения interrupt:

void interrupt myhandler()
(*

*)

Вы должны объявлять функции прерывания с типом void.
Функции прерывания могут быть объявлены с любой моделью па-
мяти. Для всех моделей памяти, кроме huge, DS устанавливает-
ся на сегмент данных программы. В случае модели huge DS ус-
танавливаетсяна сегмент данных модуля.

Модификатор volatile

В C++ volatile имеетспециальное значение для функций
компонентов класса. Если вы объявили объект volatile, вы мо-
жете использовать для него только функции компонентов
volatile.

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

volatile int ticks;
interrupt timer()
(*
ticks++;
*)
wait(int interval)
(*
ticks = 0;
while (ticks < interval); // не делает ничего Эти подпрограммы (предполагается, что timer правильно связана с аппаратным прерыванием часов) реализуют выдержкупо времени между"тиканьем" часов, заданную аргументом interval. Высоко оптимизированный компилятор не может загружать значе- ние ticks в проверку выхода из цикла while, так как цикл не изменяет значения ticks. Модификаторы cdecl и pascal Turbo C++ позволяет вашим программам легко вызывать - 50 - подпрограммы, написанные на других языках, и наоборот.При смешанном программировании приходится иметь дело с двумя важными вопросами: идентификаторы и передача параметров. В Turbo C++ все глобальные идентификаторы сохраняются в своем исходном виде (строчные, заглавныебуквы и их комбина- ции) с присоединенным в начале идентификатора знакомподчер- кивания (_), если вы не выберете опцию-u- (GenerateUnderbars...Off) в диалоговом поле Options \! Compiler \! Code Generation). На стр.32 оригинала рассказано, как использовать extern,что позволяет ссылаться на имена С из программы на C+ +. pascal В Паскале глобальные идентификаторы не сохраняются в своем исходном виде и не имеют первым символом знак подчер- кивания. Turbo C++ позволяют объявлять любые идентификаторы как имеющие тип pascal; тогда такойидентификатор преобразо- вывается к верхнему регистру, и ему непредшествует знак под- черкивания. (Если идентификатор является функцией,то что также влияет на используемую последовательность передачи па- раметров;подробности см. на стр. 51 оригинала, "Модификаторы типа функции".) Опция компилятора -p (Calling Convention...Pascal в ди- алоговом поле Options \! Compiler \!Code Generation) вызыва- ет обработку функций (и указателей на эти функции) как если бы они имели тип pascal. Модификатор pascal специфичен для Turbo C++; он пред- назначен для функций (и указателей функций), использующих последовательность передачи параметров Паскаля. Кроме того, функции, объявленные с типом pascal, могут тем не менее вы- зываться из подпрограмм С, если последним известно, что дан- ная функция имеет тип pascal. pascal putnums(int i, int j, int k) (* printf("And the answers are: %d, %d, and %j\n",i,j,k); *) Функции типа pascal немогут принимать переменное число аргументов, в отличие от таких функций, как printf. Поэтому в определении функции типа pascal использовать многоточие (...) нельзя. cdecl Программа main должна быть объявлена как cdecl, пос- кольку загрузочный код С всегда пытается вызвать главную процедуру (main) по соглашениям С. После компиляции программы с опцией -pвам может понадо- биться,чтобы некоторые идентификаторы сохранили регистр, в котором они были первоначально набраны, и ведущий знак под- черкивания, особенно если это идентификаторы С из другого файла. Это можно сделать, объявив этиидентификаторыкак cdecl. (Это также влияет на передачу параметров функциям). Как и pascal, модификатор cdecl специфичен для Turbo C+ +. Он используется с функциями и указателями функций. Этот- модификатор переопределяет директиву компилятора -p и позво- ляет вызывать такую функцию как правильную функцию С. Напри- мер, если вы компилируете предыдущую программус - 51 - установленной опцией -p, но желаете использовать printf, то нужно сделать следующее: extern cdecl printf(); putnums(int i, int j, int k); cdecl main() (* putnums(1,4,9); *) putnums(int i, int j, int k) (* printf("And the answers are: %d, %d, and %j\n",i,j,k); *) При компиляции такой программы с опцией -p все функции из библиотеки исполняющей системы должны иметь объявление cdecl. Если вы посмотрите файлы заголовка (такие как stdio.h), вы увидите, что с учетом этого каждая функция оп- ределена там как cdecl. Модификаторы указателей Turbo C++ имеет восемь модификаторов, влияющих на опе- рацию обращения поссылке, то есть на модификацию указателей в данные. Эти модификаторы: near, far, huge, _cs, _ds, _es, _seg и _ss. С позволяет выполнять компиляцию с использованием одной из нескольких моделей памяти. Используемая вами модель опре- деляет (помимо всего прочего) внутренний формат указателей. Например, при использованиималой данных small (tiny, small, medium)все указатели данных содержат 16-битовое смещение ре- гистра сегмента данных (DS). При использовании большой моде- ли данных (compact, large, huge)все указатели данных имеют длину 32 бита и содержат как адрес сегмента, так и смещение. Иногда, используя один размер модели данных, вам может понадобитьсяобъявить указатель, размер или формат которого отличен от текущегопо умолчанию.Это делаетсяс помощью моди- фикаторов указателей. Углубленное рассмотрение указателей near, far и huge см. на стр. 192 оригинала в главе 4, а описание нормализо- ванных указателей см. на стр. 193 оригинала. Кроме того, см. на стр. 199 оригинала обсуждение _cs, _ds, _es, _seg и _ss.

Страницы: 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

— 81 —

Округление всегда выполняется к нулю.
Операции типа сложения

Существует две операции типа сложения: + и -. Синтаксис
этих операций следующий:

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

Операция сложения +

Допустимыми являются следующие типы операндов выражения
операнд1 + операнд2:

1. Операнд1 и операнд2 оба арифметического типа.

2. Операнд1 интегрального типа, а операнд2 является
указателем на объект.

3. Операнд2 интегрального типа, а операнд1 является
указателем на объект.

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

Операция вычитания —

Допустимыми являются следующие типы операндов выражения
операнд1 — операнд2:

1. Операнд1 и операнд2 оба арифметического типа.

2. Оба операнда являются указателями на совместимые ти-
пы объектов. (Примечание: неквалифицированный тип type расс-
матривается как совместимый с квалифицированными типами
const type, volatile type и const volatile type.)

3. Операнд2 интегрального типа, а операнд1 является
указателем на объект.

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

Операции поразрядного сдвига

Существует две операции поразрядного сдвига: >.
Синтаксис этих операций следующий:

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

Операция поразрядного сдвига влево > E2 операнды Е1 и Е2 должны иметь тип
int. С Е1 и Е2 выполняются обычные целочисленные действия, а
тип результата определяется операндом Е1. Если Е2 отрицате-
лен, либо по числу разрядов больше или равен Е1, то операция
неопределена.

Результатом операции E1 >> E2 является значение E1,
сдвинутое вправо на Е2 разрядов. Если Е1 имеет тип unsigned,

то при необходимости происходит его заполнение нулями слева.
Если же Е1 имеет тип signed, то заполнение слева выполняется
знаком (0 для положительных и 1 для отрицательных значений).
Такое расширение знакового бита гарантирует, что знак у Е1
>> E2 будет таким же, как и у E1. За исключением типов со
знаком, значение E1 >> E2 представляет собой целую часть
частного.

Операции отношения

Существует четыре операции отношения: < > =. Син-
таксис этих операций следующий:

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

Операция меньше чем < В выражении E1 < E2 операнды должны удовлетворять одно- му из следующего набора условий: 1. Оба значения Е1 и Е2 - арифметического типа. 2. Оба значения Е1 и Е2 являются указателями квалифици- рованных или неквалифицированных версий совместимых типов объектов. Определение квалифицированных имен дается на стр.108 оригинала. 3. Оба значения Е1 и Е2 являются указателями квалифици- рованных или неквалифицированных версий совместимых неполных типов. В случае 1 выполняются обычные арифметические преобра- зования. Результат E1 < E2 имеет тип int. Если значение E1 меньше значения E2, то результат равен 1 (истина); в против- - 83 - ном случае результат равен 0 (ложь). В случаях 2 и 3, где Е1 и Е2 являются указателями сов- местимых типов, результат операции E1 E2 дает 1 (истина), если значение Е1 больше значения Е2;в противном случае результат равен 0 (ложь), причем используются те же способы интерпретации арифметических сравнений и сравнений указателей, что опреде- лены для операции "больше чем". К операндам применимы те же правила и ограничения. Операция меньше или равно = E2 дает 1 (истина), если значение Е1 больше или равно значению Е2. В противном случае результат равен 0 (ложь), причем используются те же способы интерпретации арифметических сравнений и сравнений указате- лей, что определены для операции "меньше чем". К операндам применимы те же правила и ограничения. Операции типа равенства Существует две операции типа равенства: == и !=. Они проверяют условие равенства операндов арифметического типа и типа указателей, следуя при этом правилам, аналогичным тем, что действуют для операцийотношения. Отметим, однако, что == и != имеют более низкий приоритет выполнения, чем операции отношения , =. Кроме того, операции == и != позво- ляют выполнять проверку равенства указателей в таких случа- ях, где операции отношения неприменимы. Синтаксис этих опе- раций следующий: выражение-типа-равенства:

Страницы: 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

enum team (* giants, cubs=3, dodgers = giants + 1 *);

константы установлены следующим образом:

giants = 0, cubs = 3, dodgers = 1

Значения констант не обязаны быть уникальными:

enum team (* giants, cubs = 1, dodgers = cubs — 1 *);

Допустимы также отрицательные инициализаторы.

Строковые литералы

— 20 —
Строковые литералы, известные также как строковые конс-
танты, образуют специальную категорию констант, используемых
для работы с фиксированными последовательностями символов.
Строковый литерал имееттип данных array ofchar и класспамя-
тиstatic, и записываетсякак последовательность произвольного
количества символов, заключенных в двойные кавычки:

«Это строковый литерал!»

Нулевая (пустая) строка записывается как «».

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

«\t\t\»Имя \»\\\tАдрес\n\n»

распечатается следующим образом:

«Имя «\ Адрес

Слову «Имя » будет предшествовать два символа табуля-
ции; слову Адрес предшествуетодин символтабуляции. Строка
заканчиваетсядвумя символами новой строки. Последователь-
ность \» обеспечивает вывод внутренних кавычек.

Строка литерала хранится в памяти как заданная последо-
вательность символов,плюс конечный пустой символ (‘\0’). Ну-
левая строка хранится в виде одного символа ‘\0’.

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

#include

main()
(*
char *p;

p = «Это пример того, как Turbo C++»
» автоматически\nвыполняет для вас конкатенацию»
» очень длинных строк,\nчто позволяет получить»
» более красивые программы.»;
printf(*p*);
*)

На выходе программы будет:

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

Для расширения строковой константы за границы строки в
качестве символа продолжения можно использовать обратную
наклонную черту (\):

put(«В действительности \
это однострочная строка символов»);
Константы и их внутреннее представление

ANSI C говорит о том, что размер и численный диапазон
базовых типовданных( и различных их модификаций) зависят от
конкретной реализации компилятора и в целом от архитектуры
компьютера, на котором он установлен. Базовыми компьютерами
дляTurbo C++ являются компьютеры семействаIBM PC (и совмес-
тимые с ними), поэтому выбор внутреннего представления раз-

— 21 —
личных типов данных в целом определяется архитектурой мик-
ропроцессоров 8088 и 80×86. В следующей таблице сведены
размеры и соответствующие диапазоны значений для типов дан-
ных, определяемых в Turbo C++. Дополнительную информацию об
этих типах данных см. на стр. 39 оригинала. Внутреннее
представление типов данных см. на рис.1.

Типы данных, размеры и диапазоны значений Таблица 1.9
————————————————————
Тип Размер Диапазон Примеры применения
————————————————————
unsigned char8 0 до 255 Малые числа и полный

набор символов PC

char8 -128 до 127 Самые малые числа и
ASCII-символы

enum 16 -32,768 до 32,767 Упорядоченные наборы
значений

unsigned int 16 0 до 65,535 Большие числа и циклы

short int 16 -32,768 до 32,767 Счетчики, малые числа,
управление циклами

int 16 -32,768 до 32,767 Счетчики, малые числа,
управление циклами

unsigned long 32 0 до 4,294,967,295 Астрономические
расстояния

long 32 -2,147,483,648 до 2,147,483,647
Большие числа, население

-38 38
float 32 3.4 x 10 до 3.4 x 10
Научные расчеты (точность
7 разрядов)

-308 308
double 64 1.7 x 10 до 1.7 x 10
Научные расчеты (точность
15 разрядов)

-4932 4932
long double 80 3.4 x 10 до 1.1 x 10
Финансовые расчеты
(точность 19 знаков)

near pointer 16 Не существует Манипулирование адресами
памяти

far pointer 32 Не существует Манипулирование адресами
памяти вне текущего
сегмента
————————————————————

Страницы: 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

Модификаторы типа функции

Модификаторы near, far и huge могут также использовать-
сякак модификаторы типа функции; т.е., они могут модифициро-
вать, помимо указателей данных, функции и указатели функций.
Кроме того,для модификации функций могут служить модификато-
ры _export, _loadds и _saveregs.

Модификаторы функций near, far и huge могут комбиниро-
ваться с модификаторами cdecl или pascal, но не с interrupt.

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

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

Функция near использует ближние (near) вызовы; функ-
цияfar или huge использует дальние (far) команды вызова.

— 52 —

В случае моделей памяти tiny, small и compact функция,
где это не было задано явно, имеет по умолчанию тип near. В
моделях medium и large по умолчанию функция имеет тип far. В
модели памяти huge по умолчанию используется тип huge.

Функция huge аналогична функции far, за исключением то-
го, что при входе вфункцию huge регистрDS устанавливается на
адрес сегмента данных исходного модуля, нодля функции far
остается неустановленным.

Модификатор _export лексически анализируется, но игно-
рируется. Он обеспечивает совместимость с исходными модуля-
ми, написанными для OS/2. Для программ в DOS модификатор
_export никакого значения не имеет.

Модификатор _loadds указывает, что функция должна уста-
навливатьрегистр DS аналогично тому, как это делает функция
huge, но не подразумевает вызовов near или far. Таким обра-
зом, _loadds far эквивалентно объявлению huge.

Модификатор _saveregsзаставляет функцию сохранитьвсе
значения регистров и затем восстановить их перед возвра-
том(за исключением явных значений возврата, передаваемых в
таких регистрах AX или DX.)

Модификаторы _loadds и_saveregs полезны при написании
подпрограмм интерфейса нижнего уровня, как например, подп-
рограммы поддержки мыши.

Сложные объявления и деклараторы

Синтаксис декларатора см. на стр.35 оригинала.Определе-
ние включает в себя деклараторы идентификаторов и функций.

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

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

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

спецификатор-класса-памятиtype D1, D2;

указывает, что каждое вхождение D1 или D2 в выражение
будет рассматриваться как объект типа «type» и с заданным
«классом-памяти». Тип имени-декларатора, входящего в декла-
ратор, должно быть некоторой фразой, содержащей type, напри-
мер «type», «pointer to type», «array of type», «function
returning type» или «pointer to function returning type», и
т.д.

Например, в объявлениях

int n, nao[], naf[3], *pn, *apr[], (*pan)[], &nr=n

— 53 —
int f(void), *frp(void), (*pfn)(void);

каждый из деклараторов мог бы быть использован в ка-
честве значения переменной (правой части) (или, возможно, в

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

Сложные объявления Таблица 1.17
————————————————————
Синтаксис Подразумеваемый тип имени Пример
————————————————————
type имя; type int count;
type имя[] (открытый) массив array of type int count[1];
type имя[3]; Фиксированный массив из трех int count[3];
элементов типа type
(name[0],name[1],name[3])
type *имя; Указатель на type int *count;
type *имя[]; (открытый) массив указателей int *count[];
type *(имя[]) То же самое int *(count[]);
type (*имя)[]; Указатель на (открытый) массив int
(*count)[];
типа type
type &имя; Ссылка на тип type (только С++) int &count;
type имя(); Функция, возвращающая тип type int count();
type *имя(); Функция, возвращающая указатель int *count();
на тип type
type *(имя()); То же самое int *(count());
type (*имя)(); Указатель на функцию, возвращающую int
(*count)();
тип type
————————————————————

Отметим необходимость круглых скобок в (*имя)[] и
(*имя)(), поскольку приоритет декларатора массива [] и дек-
ларатора функции () выше, чем декларатора указателя *. Круг-
лые скобки в *(имя[]) опциональны.

Указатели

Обсуждение создания ссылок и обращения по ссылкам (ра-
зыменования) см. на стр.80 оригинала.

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

Два этиклассауказателей имеют отличные друг от друга
свойства, назначения и правила манипулирования, хотя и те и
другие разделяют между собойопределенные операцииTurbo C++.
Вообще говоря, указатели функций используются для доступа к
функциям и для передачиодних функцийдругим в качествеаргу-
ментов; выполнение арифметических операцийс указателямифунк-
ций не допускается. И напротив, указателиобъектов при скани-
ровании массивов или более сложных структур памяти регулярно
инкрементируются и декрементируются.

Хотя указатели содержат числа сбольшинством характерис-
тик типаunsigned int, они имеют свои собственные правила и
ограничения на присвоения, преобразования ивыполнение с ними
арифметических действий. Примеры в следующих нескольких раз-
делах иллюстрируют эти правила и ограничения.

Указатели объектов

— 54 —
«Указатель на объект типа type» содержит адрес (то есть
указывает) объекта с типом type. Поскольку указатель сам по
себе является объектом, то вы можете установить указатель на
указатель (и т.д.). В число прочих объектов,на которые обыч-
но устанавливается указатель, входят массивы, структуры,объ-
единения и классы.

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

Указатели функций

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

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

В С++, где контроль типов данных болеестрогий, указа-
тель функции имеет тип «указатель функции принимающей агру-
менты типа type и возвращающей тип type». Действительно, в С
функция, определенная с типами аргументов, также будет иметь
данный, более узкий тип. Например,

void (*func)();

В С это будет указатель функции, не возвращающей ника-

Страницы: 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

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

Операция проверки равенства ==

В выражении E1 == E2 операнды должны удовлетворять

— 84 —
одному из следующего набора условий:

1. Оба значения Е1 и Е2 — арифметического типа.

2. Оба значения Е1 и Е2 являются указателями квалифици-
рованных или неквалифицированных версий совместимых типов.

3. Одно из значений, Е1 или Е2, является указателем
объекта неполного типа, а второй — указателем на квалифици-
рованную или неквалифицированную версию void.

4. Одно из значений, Е1 или Е2, является указателем, а
второе — константой типа пустого указателя.

Если Е1 и Е2 имеют тип, являющийся допустимым типом для
операций отношения, то применимы правила, подробно описанные
для операций отношения типа Е1 < E2, E1

Страницы: 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

Turbo C++ Version 1.0 Programmer’s Guide

КОМПЬЮТЕРНАЯ ЛИТЕРАТУРА

LIB.com.ua [электронная библиотека]: : TURBO C++ Version 1.0 Programmer’s Guide

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

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

— присваивание
— декремент
— вызов функции
— запятая
Описание операций

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

Расширения C++ предлагают дополнительные операции для

— 23 —
доступа к компонентам класса и их объектам, атакже механизм
перегрузки операций. Перегрузка позволяет переопределять
действие любых стандартных операций применительно к объектам
заданного класса. В данном разделе мы ограничимся рассмотре-
нием стандартных операций TurboC++. Перегрузка рассматрива-
ется, начиная со стр.124 оригинала.

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

Операции в Turbo C++ определяются следующим образом:

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

[] () . -> ++ —
& * + — тильда !
sizeof / % > < > = == != ^
\! && \!\! ?: = *=
/= %= += -= =
&= ^= \!= , # ##

Операции # и ## используются только препроцессором (см.
стр. 133 оригинала).

Следующие операции являются специфичными для C++:

:: .* ->*

За исключением операций [], () и ?:, служащих для запи-
си выражений в скобках, многосимвольные операции рассматри-
ваются в качестве одной лексемы. Лексема одной и той же опе-
рации может иметьнесколько интерпретаций, в зависимости от
контекста. Например,

A * B Умножение
*ptr Обращение по ссылке

A & B Поразрядное И
&A Операция адресации
int & Модификатор указателя (C++)

label: Метка оператора
a ? x : y Условный оператор

void func(int n); Объявление функции
a = (b+c)*d; Выражение со скобками

a, b, c; Выражение с запятой
func(a, b, c); Вызов функции

a = -b; Поразрядное вычитание (дополнение до
единицы)
-func() (*delete a;*) Деструктор (C++)

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

& Операция адресации
* Операция обращения по ссылке
+ Унарный плюс
— Унарный минус
тильда Поразрядное дополнение (дополнение до
единицы)
! Логическое отрицание

— 24 —
++ Префикс: пред- инкремент;
Постфикс: пост- инкремент
— Префикс: пред- декремент;
Постфикс: пост- декремент
Бинарные операции

Операции типа сложения + Бинарный плюс (сложение)
— Бинарный минус (вычитание)

Операции типа умножения * Умножение
/ Деление
% Остаток от деления

Операции сдвига > Сдвиг вправо

Поразрядные операции & Поразрядное И
^ Поразрядное исключающее ИЛИ
\! Поразрядное включающее ИЛИ

Логические операции && Логическое И
\!\! Логическое ИЛИ

Операторы присваивания = Присваивание
*= Присвоить произведение
/= Присвоить частное
%= Присвоить остаток
+= Присвоить сумму
-= Присвоить разность
= Присвоить сдвиг вправо
&= Присвоить поразрядное И
^= Присвоить поразрядное исключающее
ИЛИ
\!= Присвоить поразрядное ИЛИ

Операции отношения < Меньше > Больше
= Больше или равно

Операции равенства == Равно
!= Не равно

Операции выбора . Прямой селектор компонента
компонента -> Косвенный селектор компонента

Операции с компонентами :: Доступ/разрешение контекста
класса .* Обращение через указатель
к компоненту класса
->* Обращение через указатель
к компоненту класса

Условные операции a ? x : y «Если a то x иначе y»

Операция запятой , Вычислить, например, a, b, c
слева — направо

Функции этих операций,также как их синтаксис, приоритет
и свойства ассоциативности рассматриваются, начиная со стр.
73 оригинала.

Пунктуаторы

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

— 25 —
пунктуатор: одно из
[ ] ( ) (* *) , ; : … * = #

Квадратные скобки

[] (открывающая и закрывающая квадратные скобки) указы-
вают на индексы одно- и многомерных массивов:

char ch, str[] = «Stan»
int mat[3][4]; /* матрица 3 x 4 */
ch = str[3]; /* 4-й элемент */

Круглые скобки

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

d = c * (a + b); /* переопределение нормального приори-
тета */
/* выполнения операций */
if (d == z) ++x; /* важно при использовании условных
операций */
func(); /* вызов функции без аргументов */
int (*fptr)(); /* объявление указателя функции */
fptr = func; /* отсутствие () означает указатель функ-
ции */
void func2(int n); /* объявление функции с аргументами */

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

#define CUBE(x) ((x) * (x) * (x))

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

Страницы: 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