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

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

Turbo C++ Version 1.0 Programmer’s Guide

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

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

— 43 —

Методы стандартных арифметических преобразований Таблица 1.15
————————————————————
Тип Преобразование вМетод
————————————————————
char intРасширение нулем или знаком
(в зависимости от умолчания
для типа char)

unsigned char intЗаполнение старшего байта
нулем (всегда)

signed char intРасширение знаком (всегда)

short intТо же значение

unsigned short unsigned int То же значение

enum intТо же значение
————————————————————

Специальные преобразования типов char, int и enum

Обсуждаемые в данном разделе преобразования специфичны
для Turbo C++.

Присваивание объекта типа signed char (например,пере-
менной) интегральномуобъекту вызывает автоматическое расши-
рение знаком. Объекты типа signed char используетрасширение
знаком всегда; объекты типаunsigned charпри преобразовании
вint всегда устанавливают старший байт в ноль.

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

Инициализация

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

— нулем, если это объект арифметического типа
— null, если что указатель

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

Синтаксис инициализаторов следующий:
инициализатор
= выражение
= (*список-инициализаторов*)*)
(список выражений)

список-инициализаторов
выражение
список-инициализаторов, выражение
(*список-инициализаторов*)*)

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

— 44 —

1. Число инициализаторов в списке инициализаторов не
может превышать число инициализируемых объектов.

2. Инициализируемый элемент должен быть типа объекта
или массивом неизвестной размерности.

3. Все выражения должны являться константами, если они
находятся в одном из следующих мест:

а. в инициализаторе объекта, имеющего статическую дли-
тельность (в Turbo C++ не требуется)

b. в списке инициализаторов для массива, структуры или
объединения (также допустимы выражения с использованием
sizeof)

4. Если объявление идентификатора имеет контекст блока,
и идентификатор имеет внешнюю или внутреннюю компоновку,
объявление не может иметь инициализатор для идентификатора.

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

памяти.

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

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

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

Массивы, структуры и объединения

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

int days[7] = (* 1, 1, 1, 1, 1, 1, 1)

Этими правилами можновоспользоваться для инициализации
символьных массивов и широких символьных массивов:

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

— 45 —
инициализирует последовательно расположенные элементы масси-
ва. Например, вы могли объявить:

char name[] = (* «Unknown» *);

установив тем самым массив из восьми элементов, элемен-
ты которого равны ‘U'(для name[0]), ‘n’ (для name[1]), и
т.д. (включая нулевой терминатор.)

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

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

struct mystruct (*
int i;
char str[21];
double d;
*) s = (* 20, «Borland», 3.14 *);

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

Простые объявления

Простые объявления идентификаторов переменных имеют
следующий шаблон:

тип-данных перем1 , перем2 ,…;

где перем1, перем2, … это произвольная последователь-
ность отдельных идентификаторов с опциональными инициализа-
торами. Каждая из переменных объявляется с указанным ти-
пом-данных. Например,

int x = 1, y = 2;

создает две целочисленных переменных x и y (и
инициализирует их значениями 1 и 2, соответственно).

Это былиобъявления определения; при этом распределялась
память и выполнялась инициализация.

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

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

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

Спецификаторы класса памяти

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

auto register typedef
extern static

— 46 —

Использование спецификатора класса памяти auto

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

Использование спецификатора класса памяти extern

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

Использование спецификатора класса памяти register

Спецификатор класса памяти registerдопустим только в
объявлениях локальных переменных и параметров функций. Он
эквивалентен класса auto, за исключением того, что компиля-
тору в данном случае делается запрос о размещении при воз-
можности данной переменной в регистре. Распределение для пе-
ременной регистра может значительно уменьшить размер
программы и увеличить скорость ее выполнения во многих слу-
чаях. Однако, поскольку TurboC++ итак предпринимает мерыдля
возможного размещения переменных в регистре, необходимость в
явном задании ключевого слова register возникает редко.

Turbo C++ позволяет вам выбрать опции размещения пере-
менных в регистрах в диалоговом поле Options \! Compiler \!
Optimization. При выборе опции Automatic TurboC++ сделает
попытку распределить регистры даже еслиспецификаторы класса
памяти register не задавались.

Использование спецификатора класса памяти static

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

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

Использование спецификатора класса памяти typedef

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

static long int biggy;
typedef long int BIGGY;

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

— 47 —
этомкакого-либо объекта времени выполнения. 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 Переменные отменяет учет регистра идентифи-

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

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.

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

TURBO C++

Version 1.0

Programmer’s Guide

.
— 2 —

Оглавление

Введение……………………………………………
Содержание данного руководства……………………….
Глава 1 Стандарт языка Turbo C++……………….
Синтаксис и терминология…………………………….
Грамматические правила структуры фраз и лексики языка…..
Пробельные символы………………………………….
«Склеивание» строк символом \………………………
Комментарии………………………………………..
Комментарии C…………………………………….
Вложенные комментарии……………………………..
Комментарии C++…………………………………..
Разделители комментариев и пробелы………………….
Лексемы……………………………………………
Ключевые слова……………………………………
Идентификаторы……………………………………
Константы………………………………………..
Константы и их внутреннее представление……………..
Описание операций…………………………………..
Унарные операции ………………………………..
Бинарные операции…………………………………
Пунктуаторы ……………………………………
Объявления…………………………………………
Объекты ……………………………………….
Именующие выражения (Lvalues) ……………………
Типы и классы памяти ……………………………
Контекст ………………………………………
Видимость………………………………………..
Продолжительность…………………………………
Единицы трансляции ……………………………….
Компоновка ………………………………………
Синтаксис объявления………………………………..
Предварительные определения ……………………..
Возможные объявления ……………………………
Внешние объявления и определения …………………
Спецификаторы типа ……………………………….
Таксономия типа ………………………………..
Фундаментальные типы ……………………………
Инициализация…………………………………….
Простые объявления………………………………..
Спецификаторы класса памяти………………………..
Модификаторы……………………………………..
Сложные объявления и деклараторы……………………
Указатели………………………………………….
Указатели объектов………………………………..
Указатели функций…………………………………
Объявления указателей …………………………..
Указатели и константы …………………………..
Арифметические операции с указателями …………….
Преобразования указателей………………………….
Объявления ссылок в С++ …………………………
Массивы …………………………………………
Функции……………………………………………
Объявления и определения ………………………..
Объявления и прототипы ………………………….
Объявления ………………………………………
Объявления формальных параметров …………………
Вызовы функций и преобразования аргументов ………….
Структуры………………………………………….
Структуры без тегов и определения типов (typedef)…….
Объявления компонентов структуры …………………
Структуры и функции …………………………….
Доступ к компоненту структуры ……………………

Отличный хостинг поддерживающий Perl, PHP (C++) —

— 3 —
Выравнивание по границе слова ……………………
Пространство имен структур ………………………..
Неполные объявления …………………………….
Битовые поля …………………………………..
Объединения………………………………………..
Объявления объединений …………………………..
Перечислимые данные…………………………………
Выражения………………………………………….

Выражения и Turbo C++ …………………………..
Последовательность вычислений ……………………
Ошибки и переполнения …………………………..
Семантика операций………………………………….
Постфиксные и префиксные операции…………………..
Операции инкремента и декремента …………………
Унарные операции ……………………………….
Операция sizeof ……………………………….
Операции типа умножения …………………………
Операции типа сложения ………………………….
Операции поразрядного сдвига …………………….
Операции отношения ……………………………….
Операции типа равенства …………………………
Операция поразрядного И & ………………………..
Операция поразрядного исключающего ИЛИ ^……………
Операция поразрядного включающего ИЛИ \!……………
Операция логического И &&…………………………
Операция логического ИЛИ \!\!……………………..
Условная операция ?:………………………………
Операции присвоения …………………………….
Операция с запятой………………………………..
Операторы………………………………………….
Блоки …………………………………………
Операторы-с-метками …………………………….
Операторы-выражения …………………………….
Операторы выбора ……………………………….
Операторы итерации ……………………………….
Операторы перехода ……………………………….
С++……………………………………………….
Ссылки ………………………………………..
Операция доступа к контексту …………………….
Операции new и delete …………………………..
Классы ………………………………………..
Виртуальные базовые классы ………………………..
«Друзья» классов (friend)………………………….
Конструкторы и деструкторы ………………………..
Конструкторы …………………………………..
Деструкторы ……………………………………
Перегруженные операции ………………………….
Операции-функции ………………………………..
Виртуальные функции……………………………….
Абстрактные классы ……………………………….
Контекст С++ …………………………………..
Директивы препроцессора Turbo C++…………………….
Пустая директива # ……………………………….
Директивы #define и #undef ………………………..
Включение файлов директивой #include ……………..
Условная компиляция …………………………….
Директива управления нумерацией строк #line ……….
Директива #error ……………………………….
Директива #pragma…………………………………
Предопределенные макросы ………………………..
Глава 2. Перекрестные ссылки по библиотеке исполняющей
системы……………………………………………
Зачем нужен доступ к исходным кодам библиотеки исполняющей
системы…………………………………………..
Файлы заголовка Turbo C++……………………………
Категории библиотечных подпрограмм……………………
Глава 3 Потоки С++…………………………….

— 4 —
Новые потоки вместо старых…………………………..
Использование потоков 2.0……………………………
Что такое поток? ………………………………..
Библиотека iostream ………………………………
Четыре стандартных потока ………………………..
Вывод …………………………………………
Ввод…………………………………………….
Инициализация потоков ……………………………
Простой ввод/вывод в файл ………………………..
Состояния ошибки потока ввода/вывода………………..
Использование потоков прошлых версий………………….
Рекомендации по переходу к потокам версии 2.0………….
Глава 4 Модели памяти, операции с плавающей точкой и
оверлеи……………………………………………
Модели памяти………………………………………
Регистры 8086…………………………………….
Сегментация памяти………………………………..
Указатели………………………………………..
Шесть моделей памяти………………………………
Программирование с использованием различных моделей памяти
адресные модификаторы……………………………..
Объявление ближних или дальних функций …………….
Объявление указателей near, far или huge…………….
Использование библиотечных файлов…………………..
Компоновка смешанных модулей ……………………..
Опции типа чисел с плавающей точкой…………………..
Эмулирование платы 80х87…………………………..
Получение кода только для машин с 80х87 ……………
Получение кода без операций с плавающей точкой ……..
Опция быстрых вычислений с плавающей точкой ………..
Переменная операционной среды 87……………………
Регистры и 80х87 ………………………………..
Математические операции с комплексными числами…………
Использование двоично-десятичной (BCD) математики…….
Использование оперативной памяти Turbo C++…………….
Оверлеи (VROOMM)……………………………………
Работа программ с оверлеями………………………..
Требования……………………………………….
Использование оверлеев ……………………………
Разработка программ с перекрытиями………………….
Свопинг ………………………………………..
Дополнительная память (EMS)………………………..

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

Расширенная память (Ext)…………………………..
Глава 5 Видео функции…………………..
Несколько слов о видео режимах……………………….
Несколько слов о текстовых и графических окнах…………
Что такое окно ? ……………………………….
Что такое графическое окно ? ……………………..
Координаты……………………………………….
Программирование в текстовом режиме…………………..
Функции консольного ввода/вывода …………………..
Текстовые окна……………………………………
Тип text_mode…………………………………….
Цвета текста ……………………………………
Высокоскоростной вывод: переменная directvideo ………
Программирование в графическом режиме…………………
Функции библиотеки graphics………………………..
Управление цветом на CGA…………………………..
Глава 6…………………………………………….
Смешанное программирование…………………………..
Последовательности передачи параметров ……………
Подготовка к вызову .ASM из Turbo C++…………………
Упрощенные сегментные директивы …………………..
Стандартные сегментные директивы …………………
Определение данных — констант и переменных ………….
Определение глобальных и внешних идентификаторов …..
Подготовка к вызову Turbo C++ из .ASM…………………

— 5 —
Ссылки к функциям…………………………………
Ссылки к данным ………………………………..
Определение подпрограмм на языке ассемблера……………
Передача параметров……………………………….
Обработка значений возврата ……………………….
Соглашения о регистрах………………………………
Вызов функций С из модулей .ASM………………………
Псевдопеременные, встраиваемые ассемблерные коды и функции
прерывания………………………………………..
Псевдопеременные ……………………………….
Встраиваемые ассемблерные коды …………………..
Функции прерывания………………………………..
Практические примеры программ низкого уровня ………
Глава 7 Сообщения об ошибках………………….
Сообщения об ошибках времени выполнения……………….
Сообщения об ошибках компилятора……………………..
Фатальные ошибки……………………………………
Ошибки…………………………………………….
Предупреждения……………………………………..
Приложение АСтандарты ANSI, зависящие от
реализации…………………………………………
.
— 6 —

Введение

Документ «Начало работы» содержит обзор всего комплекта
документации к Turbo C++. Информация о том, как с наибольшей
эффективностью использовать Руководства по Turbo C++, содер-
жится во введении и главе 2 этого документа.

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

Прочесть документ «Начало работы» следует, если:

1. Вы ранее никогда не программировали ни на одном язы-
ке.
2. Вы ранее программировали, но не на C, и желаете про-
честь введение в язык C.
3. Вам нужна информация о том, как установить на компь-
ютере Turbo C++.

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

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

Содержание данного руководства

Глава 1:»Стандарт языка Turbo C++» описывает язык Turbo
C++. Здесь приводятся все отличия от стандарта ANSI C. Дан-
ная глава также включает справочник по языкам C и C++.

Глава 2: «Перекрестные ссылки по библиотеке управляющей
системы» содержит информацию об исходных кодах библиотеки
исполняющей системы. Здесь также описаны файлы заголовков и
приводятся перекрестные ссылки по библиотеке управляющей
системы, организованные по субъектам библиотеки. Например,

если вы хотите выяснить, какие функции относятся к графике,
вы должны обратиться к разделу данной главы «Графика».

Глава 3:»Потоки C++» рассказывает, как использовать
библиотеку потоков C++.

Глава 4:»Модели памяти, операции с плавающей точкой и
оверлеи» рассматривает модели памяти, программирование со
смешанными моделями памяти, вычисления с плавающей точкой и
оверлеями.

Глава 5:»Видео-функции» посвящена обработке в Turbo C++
текстов и графических изображений.

Глава 6:»Интерфейс с языком ассемблера» говорит о том,
как нужно писать программы на языке ассемблера, чтобы они
правильно работали при вызове из программ на Turbo C++.

Глава 7: «Сообщения об ошибках» перечисляет и объясняет
все фатальные ошибки, ошибки и предупреждения исполняющей

— 7 —
системы и компилятора, а также дает возможные рекомендации
по их устранению.

Приложение А: «Стандарты ANSI, зависимые от реализа-
ции» описывает те аспекты стандарта ANSI C, которые были оп-
ределены с некоторой степенью свободы или не были определены
вообще в стандарте ANSI. Следовательно, эти аспекты могут
варьироваться в зависимости от конкретной реализации. Данное
приложение сообщает о том, как Turbo C++ поступает в отноше-
нии каждого из этих аспектов.

Глава 1 Стандарт языка Turbo C++

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

Turbo C++ реализует стандарт ANSI C, разработанный тех-
ническим комитетом X3J11 между июнем 1983 и декабрем 1988
гг., с некоторыми расширениями, оговариваемыми вданномтекс-
те. Вы имеете возможность устанавливать опции компилятора,
которые будут предупреждать вас о том, чтотакие расширения
встретилисьпри работе компилятора. Вы можете также настроить
компилятор таким образом, чтобы он рассматривал ключевые
слова расширений Turbo C++ в качестве нормальных идентифика-
торов (см. Главу 4,»Компилятор командной строки», в Руко-
водстве пользователя).

Существуют также «согласующие» расширения, включаемые
посредством директив #pragma, предлагаемых стандартом ANSI
C, предназначенные для работы с нестандартными, зависимыми
от конкретной реализации средствами языка.

Turbo C++ является также полной реализацией AT&TC++
версии 2.00, объектно-ориентированного надмножества C, раз-
работанного Бьерном Строструпом из AT&T Bell Laboratories.
Помимо того,что C++ дополняет C многими новыми средствами и
возможностями, он также и отличен от него в большей или
меньшей степени. В настоящей главе содержатся замечания по
этим отличиям. Все средства языка Turbo C++,имеющие отклоне-
ния от C++, более подробно рассматриваются, начиная со стра-
ницы 98.

Синтаксис и терминология

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

внешнее-определение:
определение-функции
объявление

— 8 —

восьмеричная цифра: одно из
0 1 2 3 4 5 6 7

Опциональные элементы конструкции заключаются в угловые
скобки:

целочисленный-суффикс:
суффикс-целого-без-знака

В данной главеслово «аргумент» везде используется для
обозначения действительного значения, передаваемогопри вызо-

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

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

Грамматические правила лексикиязыка Turbo C++ описаны
на стр. 5 — 58 оригинала; грамматические правила структуры
фраз Turbo C++ описаны на стр. 58 — 98 оригинала.

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

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

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

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

Пробельные символы

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

int i; float f;

и

— 9 —
int i ;
float f;

лексически идентичны, а их лексический анализ в обоих
случаях дает шесть лексем:

int i ; float f ;

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

char name[] = «Borland International»;

разбивается на семь лексем, включая и лексему строки
литералов «Borland International».

«Склеивание» строк символом \

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

«Borland \
International»

будет рассматриваться как «Borland International» (до-
полнительную информацию см. на стр. 17 оригинала, «Строковые
литералы»

Комментарии

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

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

Традиционный комментарий C представляет собой любую
последовательность символов, помещаемую послепары симво-
лов/*. Признаком конца комментарияслужитперваяпара символов*
/, встретившаяся после исходной пары /*. После выполнения
макрорасширения вся эта последовательность целиком, включая
четыре разделительных символа комментария,заменяется на один
пробел. Отметим, чтонекоторые реализации C удаляют коммента-
рии, не заменяя их на пробелы.

Turbo C++ не поддерживает не-мобильной стратегии встав-
ки лексем с помощью /**/. Вставка лексем в Turbo C++ выпол-
няетсяпри помощи заданной ANSI пары символов ##, следующим
образом:

#define VAR(i,j) (i/**/j) /* не будет работать */
#define VAR(i,j) (i##j) /* в Turbo C++ будет работать */
#define VAR(i,j) (i ## j) /* также будет работать */

В Turbo C++

— 10 —

int /* объявление */ i /* как счетчика */;

после лексического анализа даст

int i ;

то есть три лексемы: Int I ;

Вложенные комментарии

ANSI C не разрешаетвложенность комментариев. Попытка
комментировать приведенную выше строку в виде

/*int /* объявление */ i /как счетчика */; */

окончится неудачей, поскольку область действия первой
пары /* будет ограничена первой парой */. Это даст в резуль-
тате лексического анализа

i ; */

что приведет к генерированию состояния синтаксической
ошибки.

По умолчанию Turbo C++ не позволяет вложенность коммен-
тариев, однако это умолчание может быть переопределено опци-
ей компилятора. Разрешить вложенность комментариев можно ли-
бо при помощи опции -C (компилятора командной строки), либо
через меню интегрированной среды программирования
O\!C\!Source Options.

Комментарии C++

Для создания вкоде C комментариеввы можете также ис-
пользовать символы //. Это средство специфично для Turbo
C++.

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

class X (* // это комментарий
… *);

Разделители комментариев и пробелы

В редких случаях пробелы перед /* и // или после */,
хотя и не являются синтаксически обязательными, нопозволяют
избежать проблем, связанных с мобильностью. Например, код C++

int i = j//* деление на k*/k;
+m;

при лексическом анализе дастint i = j +m; а не

int i = j/k;
+m;

как это можно было бы ожидать по традиционным соглаше-
ниям C. Более удобочитаемая форма

int i = j/ /* деление на k*/ k;
+m;

— 11 —
позволяет избежать этой проблемы.

Лексемы

Turbo C++ распознает лексемы шести классов: ключевые

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

ких значений. В С++ это указатель функции, не принимающей
никаких аргументов и не возвращающей никаких значений. В
примере

void(*func)(int);

*func это указатель функции, принимающей аргумент int и
не возвращающей никаких значений.

Объявления указателей

Подробное описание типа void см. на стр.39 оригинала.

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

Если type есть любой предопределенный или определенный
пользователем тип, включая void, то объявление

type *ptr;/* Опасно — неинициализированный указатель */

— 55 —
объявит ptr как «указатель на тип type». К объявленному
таким образомобъекту ptr применимы все правила, связанные с
контекстом, продолжительностью и видимостью.

Указатель со значением null это адрес, гарантированно
отличный от любого допустимого указателя, используемого в
программе. Присвоение указателю целой константы 0 присваива-
ет указателю значение null.

Указатель типа «указатель на void» не следует путать с
нулевым (null) указателем. Объявление

void *vptr;

объявляет, что vptr — это родовой указатель, которому-
может быть присвоено любое значение «указатель на тип type»
без выдачи компилятором сообщений. Присвоения без правильно-
го приведения типов между «указателем на тип type1» и «ука-
зателем на тип type2», где type1 и type2 это различные типы,
может вызвать предупреждение или ошибку компилятора. Если
type1 это функция, а type2 нет (или наоборот), присваивания
указателей недопустимы. Если type1 это указатель на void,
приведения типов не требуется. Если type2 это указатель на
тип void, то в С приведение не нужно.

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

char near *ncp;
char far *fcp;
char huge *hcp;
fcp = ncp; // допустимо
hcp = fcp; // допустимо
fcp = hcp; // недопустимо
scp = fcp; // недопустимо
scp = (char nesr*)fcp; // теперь допустимо
Указатели и константы

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

int i; // i это целое;
int * pi; // pi это указатель на i
// (неинициализированный)
int * const cp = &i; // cp это указатель-константа на int
// const
int ci = 7; // ci это константа int const
int * pci; // pci это указатель наконстанту ci
const int * const cpc = &ci; // cpc это указатель-конс-
танта
// на константу int

Следующие присвоения допустимы:

i = ci; // Присвоить const int переменной int
*cp = ci; // Присвоение const int объекту, на
// который указывает
// указатель-константа
++pci; // Инкремент указателя на константу
pci = cpc; // Присвоение константы-указателя-на

// константу указателю-на-константу

— 56 —

Следующие присвоения недопустимы:

ci = 0; // Присвоение значений константе
// const int недопустимо
ci—; // Изменение константы недопустимо
*pci = 3; // Присвоение объекту, на который
// указывает указатель-на-константу
// недопустимо
cp = &ci; // Присвоение константе-указателю,
// даже если ее значение не будет
// изменено, недопустимо
cpc++; // Изменять указатель-константу
// недопустимо
pi = pci; // Если бы такое присвоение было
// разрешено, вы могли бы присваивать
// *pci (константе), присваивая *pi
// что недопустимо

Аналогичные правила относятся и к модификатору
volatile.Отметим, что const и volatile могут появляться в
качестве модификаторов одного и того же идентификатора.

Арифметические операции с указателями

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

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

При выполнении арифметических операций с указателями
предполагается, что указатель указывает на массив объектов.
Таким образом, если указатель объявлен как указатель на
type, то прибавление к нему целочисленного значения переме-
щает указатель на соответствующее количество объектов type.
Если type имеет размер 10 байтов, то прибавление целого чис-
ла 5 к указателю этого типа перемещает указатель в памяти на
50 байт. Разность представляет собой число элементов масси-
ва, разделяющих два значения указателей. Например, если ptr1
указывает на третий элемент массива, а ptr2 на десятый, то
результатом выполнения вычитания ptr2 — ptr1 будет 7э

Когда с «указателем на тип type» выполняется операция
сложения или вычитание целого числа, то результат также бу-
дет «указателем на тип type». Ецли type неявляется массивом,
то операнд указателя будет рассматриваться как указатель на
первый элемент «массива типа type» длиной sizeof(type).

Конечно, такого элемента, как «указатель на следующий
за последним элемент», однако указатель может принимать это
значение. Если P указывает на последний элемент массива, то
значение P+1 допустимо, но P+2 неопределено. Если P указыва-
ет на элемент за последним элементом массива, то допустимо
значение P-1, когда указатель установлен на последний эле-
мент массива. Однако установка указателя на элемент за пос-
ледним элементом массива ведет к непредсказуемым результатам
работы программы.

Для информации:P+n можно представить себе как перемеще-
ние указателя на (n*sizeof(type)) байт вперед, пока указа-

— 57 —
тель остается в допустимых границах (не далее первого за
концом массива элемента).

Вычитание междудвумя указателями на элементы одного и
того же массива дает интегральное значение типа ptrdiff_t,
определенное в stddef.h (signed long для указателей huge и
far; signed intдля всех прочих). Данное значение представля-
ет собой разность между индексами двух указанных элементов,
при условии вхождения в диапазоне ptrdiff_t. В выражении
P1P2, где P1 и P2 это указатели на тип type (или указатели
на квалифицированный тип), P1 и P2 должны указывать на су-
ществующие элементы или на следующий за последним элемент.
если P1 указывает на i-й элемент, а P2 указывает на j-й эле-
мент, то P1-P2 имеет значение (i-j).

Преобразования указателей

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

char *str
int *ip
str = (char*)ip;

В более общем виде, приведение (type*) преобразует ука-
затель в тип «указатель на тип type».

Объявления ссылок в С++

Ссылочные типы С++ тесно связаны с типами указателей.

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