рефераты

рефераты

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

Меню

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

Первое объявление создает 32-битовый объект типа long int, со статической продолжительностью существования и именем biggy. Второе объявление устанавливает идентификатор BIGGY в качестве спецификаторановоготипа, не создавая при этомкакого-либо объекта времени выполнения. BIGGY можно использовать в последующих объявлениях,там, где допустимо задаватьспецификатор типа. Например,

extern BIGGY salary;

имеет тот же эффект, что и

extern long int salary;

Хотя данный простой пример может быть равным образом реализован при помощи #define BIGGY long int, в более сложных случаях typedef позволяет добиться большего, нежели с помощью текстовых подстановок.

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

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

typedef double (*PFD)();

PFD array-pfd[10];

/* array_pfd это массив из 10 указателей на функции,

возвращающие значения типа double  */

Нельзя использовать идентификаторы typedef со спецификаторами других типов:

unsigned BIGGY pay;   /* НЕДОПУСТИМО */

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

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

Модификаторы Turbo C++  Таблица 1.16

Модификатор   Используется с   Использование

const   Только переменными  Предотвращает изменения объекта

volatile                    Только переменными Предотвращает распределение

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

В С++ const и volatile расширены и включают классы и функции.

Расширения Turbo C++

cdecl                    Функции   Устанавливает соглашения С пере-

дачи аргументов

cdecl                    Переменные   Устанавливает учет регистра иден-

тификатора и ведущие знаки подчеркивания

pascal                        Функции   Устанавливает соглашения пере-

дачи аргументов Паскаля

pascal                        Переменные   отменяет учет регистра идентифи-

катора и ведущие знаки подчеркивания

interrupt                    Функции   Функция компилируется с дополни-

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

near,                     Переменные   Переопределяет умолчание типа

far,                     указатели   указателя, задаваемое текущей

huge   моделью памяти

_cs,                    Переменные   Указатели сегмента;

_ds,                    указатели   см. стр.199 оригинала

_es,

_seg,

_ss

near,                     Функции   Переопределяет умолчание типа

far,   функции, задаваемое текущей

huge   моделью памяти

near,                     Переменные   Определяет размещение объекта в

far,   памяти

_export                     Функции   Только OS/2. Turbo C++ это

игнорирует

_loadds                     Функции   Устанавливает регистр DS на

текущий сегмент данных

_saveregs                  Функции   Предохраняет все значения регис-

тров (кроме значений возврата)

во время выполнения функции

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

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

const float  pi= 3.1415926;

const maxint = 32767;

char  *const str= "Hello, world!"; // указатель константа

char const *str2= "Hello, world!"; // указатель на константу

Использование одного только модификатораconst эквивалентно const int.

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

pi= 3.0; /* присвоение значения константе */

i= maxint++; /* инкремент константы */

str = "Hi, there!"; /* установка указателя str на что-то еще

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

В С++ const также "скрывает" объект const и предотвращает внешнюю компоновку. При необходимости нужно использовать extern const. Указатель на const не может быть присвоен указателю на не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++ позволяет вашим программам легко вызывать подпрограммы, написанные на других языках, и наоборот.При смешанном программировании приходится иметь дело с двумя важными вопросами: идентификаторы и передача параметров.

В 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 и позволяет вызывать такую функцию как правильную функцию С. Например, если вы компилируете предыдущую программус установленной опцией -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.

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

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

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

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

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

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

В случае моделей памяти 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

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, они имеют свои собственные правила и ограничения на присвоения, преобразования ивыполнение с ними арифметических действий. Примеры в следующих нескольких разделах иллюстрируют эти правила и ограничения.

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

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

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

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

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