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

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

1. Первый символ должен являться буквой или символом подчеркивания.

Отметим, что идентификаторы в Turbo C++ значимы до любой длины.

2. По умолчанию Turbo C++ распознает только первые 32 символа в качестве значимых. Число значимых символов может быть уменьшено при помощи меню или опций командной строки, но не может быть увеличено. Используйте опцию -In TCC, либо опцию меню O\!C\!S\!Identifier Length, где 1 <= n <= 32.

Идентификаторы и учет регистра

Идентификаторы в Turbo C++ учитывают регистр, и таким образом, Sum, sum и suM - это различные идентификаторы.

Глобальные идентификаторы, импортируемые из других модулей, подчиняются тем же правилам наименования и длины значимости имени, что и обычные идентификаторы. Однако, Turbo C ++ включает в себя опциюподавления учета регистра, обеспечивающую совместимость при компоновке с модулями на языках, не учитывающих регистр. Можно отменить учет регистра для глобальных идентификаторов, установив в диалоговом поле Linker в соответствующее состояние поле Options \! Linker \! Case-Sensitive Link,либо использовав опцию командной строки /C при запуске TLINK. В таком режиме глобальные имена Sum и sum рассматриваются как идентичные, и при компоновке может быть выдано предупреждение "Duplicate symbol" ("Повторяющиеся символические имена").

Исключение из этих правил составляютидентификаторы типа pascal, которые при компоновке всегда преобразовываются к верхнему регистру.

Уникальность и контекст идентификаторов

Хотя имена идентификаторов могут быть произвольными (в пределах изложенных правил), в случае использования одного и того же имени для более чем одногоидентификаторав пределах одного контекста и разделении имиодногопространства имен возникает ошибка. Повторение имен в различных пространствах имен допустимо всегда, независимо от контекста. Правила рассматриваютсяпри обсуждении контекста, начиная со стр. 29 оригинала.

Константы

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

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

Константы - определение формата Таблица 1.5

константа:

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

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

перечислимая-константа

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

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

дробная-константа <экспоненциальная-часть> <суф-

фикс-константы-с-плавающей-точкой>

последовательность-цифр экспоненциальная часть <суффикс-константы-с-плавающей-точкой>

дробная константа:

<последовательность-цифр>.<последовательность-цифр>

<последовательность-цифр>.

экспоненциальная-часть:

e <знак> последовательность-цифр

E <знак> последовательность-цифр

знак: одно из

+ -

последовательность-цифр:

цифра

последовательность-цифр цифра

суффикс-константы-с-плавающей-точкой: одно из

f l F L

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

десятичная-константа <суффикс-целочисленной-константы>

восьмеричная-константа <суффикс-целочисленной-константы>

шестнадцатиричная-константа <суффикс-целочислен-

ной-константы>

десятичная-константа:

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

десятичная-константа цифра

восьмеричная-константа:

0

восьмеричная-константа восьмеричная-цифра

шестнадцатиричная-константа:

0 x шестнадцатиричная-цифра

0 X шестнадцатиричная-цифра

шестнадцатиричная-константа шестнадцатиричная-цифра

цифра-кроме-нуля: одно из

1 2 3 4 5 6 7 8 9

восьмеричная-цифра: одно из

0 1 2 3 4 5 6 7

шестнадцатиричная-цифра: одно из

0 1 2 3 4 5 6 7 8 9

a b c d e f

A B C D E F

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

суффикс-константы-без-знака <суффикс-длинной-константы>

суффикс-длинной-константы <суффикс-константы-без-знака>

суффикс-константы-без-знака: одно из

u U

суффикс-длинной-константы: одно из

l L

перечислимая-константа:

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

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

последовательность-символов-c

последовательность-символов-c:

символ-c

последовательность-символов-c символ-c

символ-c:

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

управляющая-последовательность: одно из

\* \' \? \\

\a \b\f \n

\o \oo\ooo \r

\t \v\Xh... \xh...

Целочисленные константы

Целочисленные константы могут быть десятичными (основание системы счисления 10), восьмеричными (основание 8)или шестнадцатиричными (основание 16). При отсутствии переопределяющих суффиксов типданныхцелочисленной константы выводится из ее значения, как показано в таблице 1.6. Отметим, что правила для десятичных и не-десятичных констант различны.

Десятичные константы

Допустимыми являются десятичные константы величиной от 0 до 4,294,967,295. Константы, выходящие за указанные пределы, вызывают ошибку. Десятичныеконстанты не могут иметь ведущие нули. Целочисленнаяконстанта с ведущим нулем рассматриваетсякак восьмеричная. Таким образом,

int i = 10; /* десятичное 10 */

int i = 010; /* десятичное 8 */

int i = 0; /* десятичное 0 = восьмеричному 0! */

Отрицательные константы- это просто константы без знака, к которым применена унарная операция минус.

Восьмеричные константы

Все константыс ведущим нулем рассматриваются как восьмеричные.Если восьмеричная константа содержит недопустимые цифры 8 или 9, выдается сообщение об ошибке. Ошибка будет также выдаваться при превышении восьмеричной константой значения 037777777777.

Шестнадцатиричные константы

Все константы, начинающиеся с 0x (или 0X) рассматриваются как шестнадцатиричные. Шестнадцатиричные константы,превышающие 0xFFFFFFFF, приводят к ошибке.

Суффиксы длинных констант и констант без знака

Если законстантой следует суффикс L (или l), то такая константа будет представлена как длинная (типа long).Аналогичным образом, суффикс U (или u) делает константу константой без знака (unsigned). Если численное значение константы превышает десятичное 65,535, независимо от используемого основаниясистемы счисления, то такая константа будет иметь тип unsigned long. Суффиксы можно указывать для одной и той же константы в произвольном порядке и набирать в любом регистре: ul, lu, UL и т.д.

Тип данных константы при отсутствии каких-либо суффиксов вообще (U, u, L или l) берется из следующей таблицы,первыйже, который удовлетворяет требованиям величины этой константы:

-----------------------------------------------------------

десятичная int, long int, unsigned long int

восьмеричная int, unsigned int, long int, unsigned long int

шестнадцатиричная int, unsigned int, long int, unsigned long int

-----------------------------------------------------------

Если константа имеет суффикс U или u, то ее тип данных будет первым из типов unsigned int, insigned long int, который удовлетворит требованиям ее величины.

Если константа имеет суффикс L или l, то ее тип данных будет первым из типов long int, unsigned long int, который удовлетворит требованиям ее величины.

Если константа имеет оба суффикса u и l (ul, lu, Ul, lU,uL, Lu, LU или UL), то она будет иметь тип данных unsigned long int.

В таблице 1.6 сведены представления целочисленных констант для всех трех систем счисления. Указанные типы данных предполагают отсутствие переопределяющих суффиксов L или U.

Целочисленные константы Turbo C++ без L или U Таблица 1.6

Десятичные константы

0 до 32,767 int

32,768 до 2,147,483,647 long

2,147,483,648 до 4,294,967,295 unsigned long

> 4294967295 Генерируется ошибка

Восьмеричные константы

00 до 077777 int

0100000 до 0177777 unsigned int

02000000 до 017777777777 long

020000000000 до 037777777777 unsigned long

> 037777777777 Генерируется ошибка

Шестнадцатиричные константы

0x0000 до 0x7FFF int

0x8000 до 0xFFFF unsigned int

0x10000 до 0x7FFFFFFF long

0x80000000 до 0xFFFFFFFF unsigned long

> 0xFFFFFFFF Генерируется ошибка

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

Символьная константа - этоодин или более символов, заключенных в одинарные кавычки, например 'F', '=', '\n'. В C константы изодногосимвола имеюттип Int и имеют внутреннее представление16 бит, в то времякак старший байт слова заполняется нулем или знаком. В C++ константа из одного символа имеет тип char. Многосимвольные константы как в C, так и в C ++, имеют тип данных Int.

Управляющие последовательности

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

Обратнаянаклонная черта используетсяс восьмеричными или шестнадцатиричными числами для представления ASCII-символами управляющего кода, соответствующемуэтому значению; например, '\03' вместо Ctrl-C или '\x3F' вместо вопросительного знака. В управляющей последовательности может содержаться строка длиной до трех восьмеричных илилюбое число шестнадцатиричных цифр,при условии, чтоданноезначение лежит в допустимом для типа данных char диапазоне (от 0 до 0xff для Turbo C++). Большие значения ведутк появлению ошибки компиляции "Numeric constant too large" ("числовая константа слишком велика"). Например, восьмеричное число \777 больше максимально допустимого значения \377, и вызовет генерирование ошибки. Первое же не-восьмеричноеили не-шестнадцатиричное значение, встреченное в восьмеричнойили шестнадцатиричной управляющей последовательности, означает конец данной последовательности.

В исходной версии 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

\b

\f

\n

\r

\t

\v

\\

0x07BELЗвуковой сигнал

0x08BSЗабой

0x0CFFПеревод бланка

0x0ALFНовая строка (перевод строки)

0x0DCRВозврат каретки

0x09HTТабуляция (горизонтальная)

0x0BVTВертикальная табуляция

0x5c\Обратная наклонная черта

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

\' 0x27 ' Одинарная кавычка (апостроф)

\" 0x22 " Двойная кавычка

\? 0x3F ? Вопросительный знак

\OлюбыеO = строка до трех восьмиричных цифр

\xH любыеH = строка шестнадцатиричных цифр

\XH любыеH = строка шестнадцатиричных цифр

-----------------------------------------------------------

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

Turbo C++ поддерживает также двух-символьные константы (например, 'An', '\n\t' и '\007\007'). Эти константы представлены 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

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

при условии отсутствия явных инициализаторов. В следующем примере,

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

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

giants = 0, cubs = 3, dodgers = 1

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

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

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

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

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

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

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

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

"\t\t\"Имя \"\\\tАдрес\n\n"

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

"Имя "\ Адрес

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

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

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

#include <stdio.h>

main()

(*

char *p;

p = "Это пример того, как Turbo C++"

" автоматически\nвыполняет для вас конкатенацию"

" очень длинных строк,\nчто позволяет получить"

" более красивые программы.";

printf(*p*);

*)

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

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

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

put("В действительности \

это однострочная строка символов");

Константы и их внутреннее представление

ANSI C говорит о том, что размер и численный диапазон базовых типовданных( и различных их модификаций) зависят от конкретной реализации компилятора и в целом от архитектуры компьютера, на котором он установлен. Базовыми компьютерами дляTurbo C++ являются компьютеры семействаIBM PC (и совместимые с ними), поэтому выбор внутреннего представления различных типов данных в целом определяется архитектурой микропроцессоров 8088 и 80x86. В следующей таблице сведены размеры и соответствующие диапазоны значений для типов данных, определяемых в 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 Не существует Манипулирование адресами

памяти вне текущего

сегмента

<------- направление возрастания значимости

int \!s\!значение\! (дополнение до 2)

15 0

long int \!s\!значение \! (дополнение до 2)

31 0

----------------------

\! \!смещенный\!мантисса\!

float \!s\!порядок \! \!

31 0

--------------------------------

\! \! смещенный \! мантисса \!

double \!s\! порядок \! \!

63 0

----------------------------------------

\! \! смещенный \! \! мантисса \!

long double \!s\! порядок \! \! \!

79 0

s = знаковый бит (0 = положит, 1 = отрицат)

= позиция неявной двоичной точки

1 = целочисленный бит мантиссы: записывается в long double неявно (всегда 1) в float, double

Смещенный порядок (нормализованные значения): float:127 (7FH)

double:1023 (3FFH)

long double: 16,383 (3FFFH)

Рис.1.1 Внутренние представления типов данных

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

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

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

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

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

- присваивание

- декремент

- вызов функции

- запятая

Описание операций

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

Расширения C++ предлагают дополнительные операции для доступа к компонентам класса и их объектам, атакже механизм перегрузки операций. Перегрузка позволяет переопределять действие любых стандартных операций применительно к объектам заданного класса. В данном разделе мы ограничимся рассмотрением стандартных операций 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++)

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

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

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

+ Унарный плюс

- Унарный минус

тильда Поразрядное дополнение (дополнение до

единицы)

! Логическое отрицание

++ Префикс: пред- инкремент;

Постфикс: пост- инкремент

-- Префикс: пред- декремент;

Постфикс: пост- декремент

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

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

- Бинарный минус (вычитание)

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

/ Деление

% Остаток от деления

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

>> Сдвиг вправо

Поразрядные операции & Поразрядное И

^ Поразрядное исключающее ИЛИ

\! Поразрядное включающее ИЛИ

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

\!\! Логическое ИЛИ

Операторы присваивания = Присваивание

*= Присвоить произведение

/= Присвоить частное

%= Присвоить остаток

+= Присвоить сумму

-= Присвоить разность

<<= Присвоить сдвиг влево

>>= Присвоить сдвиг вправо

&= Присвоить поразрядное И

^= Присвоить поразрядное исключающее

ИЛИ

\!= Присвоить поразрядное ИЛИ

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

> Больше

<= Меньше или равно

>= Больше или равно

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

!= Не равно

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

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

к компоненту класса

->* Обращение через указатель

к компоненту класса

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

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

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

Пунктуаторы

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

пунктуатор: одно из

[ ] ( ) (* *) , ; : ... * = #

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

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

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 оригинала.

Фигурные скобки

(**) (Открывающие и закрывающие фигурныескобки) обозначают начало и конец составного оператора:

if (d == z)

(*

++x

func();

*)

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

if (оператор)

(**); /* недопустимое использование точки с запятой */

else

Запятая

Запятая (,) отделяет элементы списка аргументов функции:

void func(int n, float f, char ch);

Запятая часто используется как операция в "операции с запятой". Обе эти операции являются допустимыми, но для различения их вы должны использовать круглые скобки:

func(i, j); /* вызов функции с двумя аргументами */

func((exp1, exp2), (exp3, exp4, exp5)); /* также вызов функции с двумя аргументами */

Точка с запятой

Точка с запятой (;) служит терминатором оператора. Любое допустимое выражениеС (включая и пустое выражение), за которым следует (;), интерпретируется как оператор, называемый оператором выражения. Выражениевычисляется, а его значение отбрасывается. Если такое выражение не имеетпобочных эффектов, то TurboC++ может его проигнорировать.

a + b; /* a + b вычисляется, но полученное значение теряется */

++a; /* имеется побочный эффект для a, но результат ++a */

/* теряется */

; /* пустое выражение = нулевой оператор */

Точки сзапятой частоиспользуются для создания пустых операторов:

for (i = 0; i < t; i++)

(*

;

*)

Двоеточие

Двоеточие (:) служит для обозначения оператора с меткой:

stsrt: x=0;

...

goto stsrt;

...

switch (a)(*

case 1: puts("Первый");

break;

case 2: puts("Второй");

break;

...

default: puts("Ни тот, ни другой!");

break;

*)

Метки рассматриваются на стр.92 оригинала.

Многоточие

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

void func(int n, char ch,...);

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

В С++ запятую, предшествующую многоточию, можно опустить.

Звездочка (объявление указателя)

Звездочка (*) в объявлении переменной обозначает создание указателя на тип:

char *char_ptr; /* объявление указателя на тип char */

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

int **int_ptr; /* указатель на указатель на int */

double ***double_ptr /* указатель на указатель на указатель на тип double */

Звездочка также используется в качестве операции обращения через указатель, либо операции умножения:

i = *int_ptr;

a = b * 3.14;

Знак равенства (инициализатор)

Знак равенства (=) разделяет объявления переменных от списков инициализации:

char array[5] = (* 1, 2, 3, 4, 5 *);

int x = 5;

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

В списке аргументов функции С++ знак равенства указывает на значение параметра по умолчанию:

int f(int i = 0) (* ... *) /* параметр i имеет значение по умолчанию ноль */

Знак равенства используется также как операция присвоения в выражениях:

a = b + c;

ptr = farmalloc(sizeof(float)*100);

Знак фунта (директива препроцессора)

Знак фунта (#) означает директиву препроцессора, если она является первым не-пробельным символом встроке. Он задает действие компилятора, не обязательно связанное с генерацией кода. Более подробно директивы препроцессора описаны на стр.133 оригинала.

# и ## (двойной знак фунта) также используются как операции замены и слияния лексем на фазе сканирования кода препроцессором.

Объявления

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

Контекст, видимость, продолжительность и тип компоновки определяют части программы,из которых могут быть сделаны допустимые ссылки на идентификатор сцельюдоступа к соответствующему объекту. Контекст обсуждаетсяна стр.29 оригинала, видимость - на стр.30; продолжительность рассматривается, начиная со стр. 31, а тип компоновки - на стр.32.

Объекты

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

Тип используется для

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

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

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

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

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

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

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

Именующие выражения (Lvalues)

Именующее выражение представляет собой локатор объекта, выражение, которое обозначает объект. Примером именующего выражения может служить *P, где P это выражение, дающее непустой указатель. Модифицируемое именующее выражение -это идентифицирующее выражение, относящееся к объекту, к которому возможен доступ и допустимо его изменение в памяти. Указатель константы const, например, не является модифицируемым именующим выражением. Указатель на константуможетбыть изменен (а подлежащее обращению по этому указателю значение - не может).

Исторически в слове Lvalues буква L означает "левый"; это означает, что Lvalue допускается в левой части (апринимающей части) оператора присваивания. Здесь в левой части оператора присваивания допустимы только модифицируемые именующие выражения. Например, если a и b - это не являющиеся константами целочисленные идентификаторы с правильно распределеннымидля них областями памяти, тооба они являются модифицируемыми именующими выражениями, и присваиваниятипа a = 1;и b = a + b; вполне допустимы.

Значения переменной (Rvalues)

Выражение a + b не можетявляться именующим выражением, и выражение типа a + b = a недопустимо, поскольку выражение в левой части не относится кобъекту. Такие выражения часто называют значением переменной (значение правой части выражения).

Типы и классы памяти

Для связи идентификаторов с объектами требуется, чтобы каждый идентификаторимел как минимум два атрибута: класс памяти и тип (иногда его называют типомданных). КомпиляторTurboC++ определяет эти атрибуты появным или неявным объявлениям в исходном коде программы.

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

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

Контекст

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

Контекст блока

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

Контекст функции

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

Контекст прототипа функции

Идентификаторы, объявленные в списке объявлений

параметров в прототипе функции (не являющиеся частью определения функции) имеют контекст прототипа функции.Конец этого контекста совпадает с концом прототипа функции.

Контекст файла

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

Контекст класса (С++)

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

Контекст и пространства имен

Пространство имен - это контекст, в пределах которого идентификатордолженбыть уникальным. В С существует четыре раздельных класса идентификаторов:

1. Имена меток операторов goto. Эти имена должны быть уникальными в пределах функции, в которой они объявлены.

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

В С++ структуры, классы и перечислимые данные относятся к одному и тому же пространству имен.

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

4. Переменные, определения типа и компоненты перечислимых данных. Они должны бытьуникальными вконтексте, где они определены. Идентификаторы, объявленные внешними, должны быть уникальными среди переменных, объявленных вовне.

Видимость

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

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

Видимость не может выходить за пределы контекста; но контекст может превышать видимость.

...

(*

int i; char ch; // автоматическое распределение по умолчанию

i = 3; // int i и char ch в контексте и видимы

...

(*

double i;

i = 3.0e3; // double i в контексте и видима

// int i в контексте, но скрыта

ch = 'A'; // char ch в контексте и видима

*)

// double i вне контекста

i += 1; // int i видима и равна 4

... // char ch все еще в контексте и видима

// и равна 'A'

*)

... // int i и char ch вне контекста

И снова, специальные правила действуют в отношение скрытых имен классов и имен компонентов классов: специальные операции С++ позволяют доступ к скрытымидентификаторам при определенных условиях (см. стр.103 оригинала).

Продолжительность

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

Статическая продолжительность (static)

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

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

Статическую продолжительность не следует путать с файловым или глобальным контекстом. Объектможетиметьстатическую продолжительность и при этом локальный контекст.

Локальная продолжительность (local)

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

Объектыс локальнойпродолжительностью жизни, иначе

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

При объявлении переменных (например, int, char, float) спецификатор класса памяти register такжеподразумевает auto, однако компилятору при этом передается запрос (или рекомендация) о том, что при возможности данный объект желательно разместить в регистре. Turbo C++можно установить таким образом, чтобы он распределял регистрлокальной интегральной переменнойили переменной типа указатель, если какой-либо регистр свободен. Если свободных регистров нет, то переменная распределяется как auto, или динамический локальный объект, без выдачи предупреждения или генерации ошибки.

Динамическая продолжительность (dynamic)

Объекты с динамической продолжительностью жизни создаются и разрушаются конкретными вызовами функций при выполнении программы. Им распределяется памятьиз специального резерва памяти, называемого кучей, при помощи либо стандартных библиотечных функций, какнапример malloc, либо при помощи операции С++ new. Соответствующая отмена распределения выполняется при помощи free или delete.

Единицы трансляции

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

единица-трансляции:

внешнее-объявление

единица-трансляции внешнее-объявление

внешнее-объявление:

определение-функции

объявление

Слово external имеет в С несколько значений; в данном случае оно относится к объявлениям, находящимся вне каких-либо функций, и которые, следовательно, имеют контекст файла. (Отдельным свойством является внешний тип компоновки; см.следующий раздел, "Компоновка".) Любое объявление, также резервирующее память для объекта или функции, называется определением (или объявлением определения). Более подробную информацию см. в разделе "Внешние объявления и определения" на стр.36 оригинала.

Компоновка

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

Каждое вхождение конкретного идентификатора с типом компоновки external представляет тот же самый объект или функцию во всем множестве файлов и библиотек, составляющих программу. Каждое вхождение конкретного идентификатора с типом компоновки internal представляет тот же самый объект или функцию только в пределах одного файла. Идентификаторы с типом компоновки no (отсутствие) представляет уникальные элементы программы.

Ниже приводятсяправила внешней (external) и внутренней (internal) компоновки:

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

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

2. Если объявление идентификатора объекта или функции содержит спецификатор класса памяти extern, то идентификатор имеет тот же тип компоновки, что и видимое объявление идентификатора с файловым контекстом. Если такого видимого объявления не имеется, то идентификатор будет иметь внешний тип компоновки.

3. Если функция объявлена без спецификатора класса памяти, то ее тип компоновки определяется, как если бы был использован спецификатор класса памяти extern.

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

Следующие идентификаторы не имеют атрибута типа компоновки:

1. Любой идентификатор, объявленный иначе, чем объект или функция (например, идентификатор typedef).

2. Параметры функции.

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

Синтаксис объявления

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

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

Предварительные определения

СтандартANSI C вводит новуюконцепцию: предварительное определение. Любое объявление внешних данных, не имеющее спецификаторакласса памяти и инициализатора, рассматривается как предварительное определение. Еслиобъявленный идентификатор появляется в последующемопределении, то предварительное определение рассматривается,как если бы имелся спецификатор класса памяти extern .Другими словами, предварительное определение становится простым объявлением ссылки.

Если достигнут конец единицы трансляции, а для идентификатора так и не было встречено определения с инициализатором, то предварительное определение становится полным определением, а для определенного таким образом объекта резервируется неинициализированная (заполненнаянулями) область памяти. Например,

int x;

int x; /* допустимо, резервируется одна копия x */

int y;

int y = 4; /* допустимо, y инициализируется значением 4 */

int z = 5;

int z = 6; /* недопустимо, т.к. оба определения

инициализированы */

Возможные объявления

В число объектов, которые могут быть объявлены, входят:

- переменные

- функции

- классы и компоненты классов (С++)

- типы

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

- компоненты структур

- компоненты объединений

- массивы прочих типов

- перечислимые константы

- метки операторов

- макросы препроцессора

Полный синтаксис объявлений показан в следующих таблицах. Рекурсивная природа синтаксиса описателей позволяет создавать сложные описатели. Для улучшения читаемости мы пошли на использование определяемого типа (typedef).

Синтаксис объявлений Turbo C++ Таблица 1.10

объявление:

<спецификаторы-объявления> <список-деклараторов>

объявление-asm

объявление-функции

спецификация-типа-компоновки

спецификатор-объявления:

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

спецификатор-типа

спецификатор-функции

friend (только для С++)

typedef

спецификаторы-объявления:

<спецификаторы-объявления> спецификатор-объявления

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

auto

register

static

extern

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

inline

virtual

спецификатор-типа:

имя-простого-типа

спецификатор-класса

спецификатор-перечислимых-данных

спецификатор-усовершенствованного-типа

const

volatile

имя-простого-типа:

имя-класса

имя-typedef

char

short

int

long

signed

unsigned

float

double

void

спецификатор-усовершенствованного-типа:

ключ-класса идентификатор

ключ-класса имя-класса

enum имя-перечислимых-данных

ключ-класса: (только для С++)

class

struct

union

список-перечислимых-данных:

нумератор

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

нумератор:

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

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

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

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

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

extern строка (* <список-объявления> *)

extern строка объявление

список-объявления:

объявление

список-объявления объявление

Для следующей таблицы отметим, что на количество и порядок модификаторов и квалификаторов наложены ограничения. Кроме того, перечисленные модификаторыявляются единственнымдополнением синтаксиса декларатора, не входящим в стандарт ANSI C и С++. Каждый модификатор подробно описан, начиная со стр.46 оригинала.

Синтаксис декларатора Turbo C++ Таблица 1.11

список-декларатора:

инициализатор-декларатор

список-декларатораинициализатор-декларатор

инициализатор-декларатор:

имя-декларатора

список-модификаторов

операция-указателядекларатор

декларатор (список-объявления-параметров)

<список-со-квалификаторов>

(список-со-квалификаторов - только для С++)

декларатор [<выражение-типа-константы>]

список-модификаторов:

модификатор

список-модификаторов модификатор

модификатор:

cdecl

pascal

interrupt

near

far

huge

операция-указателя:

* <список-со-квалификаторов>

& <список-со-квалификаторов> (только для С++)

имя-класса = *<список-со-квалификаторов> (только для C++)

список-со-квалификаторов:

со-квалификатор <список-со-квалификаторов>

со-квалификатор:

const

volatile

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

имя

имя-класса (только для С++)

имя-класса (только для С++)

имя-typedef

имя-типа:

спецификатор-типа <абстрактный-декларатор>

абстрактный-декларатор:

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

<абстрактный-декларатор> (список-аргументов-объявления) <список-со-квалификаторов>

<абстрактный-декларатор> [<выражение-типа-константы>]

список-объявления-аргументов:

<список-объявления-арг>

список-объявления-арг, ...

<список-объявления-арг>...(только для С++)

список-объявления-арг:

объявление-аргументов

список-объявления-арг объявление-аргументов

объявление-аргументов:

спецификаторы-объявления декларатор

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

спецификаторы-объявления <абстрактный-декларатор>

спецификаторы-объявления <абстрактный-декларатор> =выражение (только для С++)

определение-функции:

<спецификаторы-объявления> декларатор <инициализатор>

тело-функции

тело-функции:

составной оператор

инициализатор:

= выражение

= (список-инициализаторов)

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

список-инициализаторов:

выражение

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

(список-инициализаторов<,>)

Внешние объявления и определения

Спецификаторы класса памяти auto и registerво внешнем объявлении появиться не могут (см. "Единицы трансляции"). Для каждого идентификатора в единице трансляции, объявленной с внешним типомкомпоновки, может существовать не более одного внешнего определения.

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

Turbo C++ позволяет затем переобъявление внешних имен, таких как массивы, структуры и объединения, добавляя информацию к ранее выполненным объявлениям. Например,

int a[] // нет размера

struct mystruct; // только тег, без объявления компонентов

...

int a[3] = [1, 2, 3]; // задание размера и инициализация

struct mystruct (*

int i, j;

*); // добавление деклараторов компонентов

Объявления классов Turbo C++ (только С++) Таблица 1.12

спецификатор-класса:

заголовок-класса (<список-компонентов>)

заголовок-класса:

ключ-класса <идентификатор> <базовый-спецификатор>

ключ-класса имя-класса <базовый-спецификатор>

список-компонентов:

объявление-компонента <список-компонентов>

спецификатор-доступа : <список-компонентов>

объявление-компонента:

<спецификаторы-объявления><список-декларатора-компонентов>;

определение-функции <;>

квалифицированное-имя;

список-декларатора-компонентов:

декларатор-компонента

список-декларатора-компонентов, декларатор-компонента

декларатор-компонента:

декларатор <pure-спецификатор>

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

pure-спецификатор:

=0

базовый-спецификатор:

:базовый-список

базовый-список:

базовый-спецификатор

базовый-список, базовый-спецификатор

базовый-спецификатор:

имя-класса

virtual <спецификатор-доступа> имя-класса

спецификатор-доступа Юvirtual> имя-класса

спецификатор-доступа:

private

protected

public

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

operator имя-типа-преобразования

имя-типа-преобразования:

спецификация-типа <операция-указателя>

инициализатор-конструктора:

: список-инициализаторов-памяти

список-инициализаторов-памяти:

инициализатор-памяти

инициализатор-памяти, список-инициализаторов-памяти

инициализатор-памяти:

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

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

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

operator операция

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

new delete sizeof

+ - * /% ^

& \! != <>

+= -= *= /=%= ^=

&= \!= << >>>>= <<=

== != <= >=&& \!\!

++ -- , ->*-> ()

[] .*

Спецификаторы типа

Спецификатор типа с одним или более опциональным модификатором используется для задания типа объявляемого идентификатора:

int i; // объявление i как целого со знаком

unsigned char ch1, ch2; // объявление двух символьных без знака

По устоявшейся традиции, если спецификатор типа опущен, то по умолчанию назначается тип signed int (или, что эквивалентно, int). Однако, в С++ встречаются ситуации, когда отсутствие спецификатора типа ведет к синтаксической неоднозначности, поэтому в практике работы с С++ используется явный ввод всех спецификаторов типа int.

Таксономия типа

Существует четыре базовые категории типа: void, scalar, function и aggregate. Типы scalar и aggregate могут далее подразделяться следующим образом:

- Scalar: арифметический, перечислимый, указатель и в С ++ ссылки

- Aggregate: массив, структура, объединение и в С++ класс

Типы делятся на фундаментальные и производные. К фундаментальным относятся: void, char, int, float и double совместно с short, long, signed, а также некоторые варианты с ними unsigned. Производные типы включают в себя указатели и ссылки на другие типы,массивы других типов, типы функций, типы классов, структуры и объединения.

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

Задав не-пустойтип type (с некоторыми предосторожностями), можно объявлять производные типы следующим образом:

Объявление типов Таблица 1.13

type t; Объект типа type

type

type

array[10]; Десять типов: array[0]-array[9]

*ptr; ptr это указатель типа

type

type

&ref=t; ref = ссылка на тип (C++)

func(void); func возвращает значение типа type

void func1(type t); func1 принимает параметр типа type

struct st (type t1; type t2); структура st содержит два типа

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

class cl (* // класс cl содержит указатель ptr на тип, плюс

// функцию, принимающую параметр type (C++)

type *ptr;

public:

void func(type*);

Тип void

Void это специальный спецификатор типа, указывающий на отсутствие каких-либо значений. Он задается в следующих ситуациях:

- Пустой список параметров в объявлении функции:

int func(void); // функция не принимает аргументов

С++ обрабатывает 0 специальным образом. См. раздел "Объявления и прототипы" на стр.60 и примеры кода на стр.61 оригинала.

- Когда объявленная функция не возвращает значений:

void func(int n); // возвращаемое значение отсутствует

- В качестве родового указателя. Указатель на void является родовым указателем на все что угодно:

void *ptr; // далее ptr может быть установлен на любой

// объект

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

extern int errfunc(); // возвращает код ошибки

...

(void) errfunc(); // значение возврата теряется

Фундаментальные типы

signed и unsigned - это модификаторы, применяемые к интегральным типам.

Фундаментальные спецификаторы типа создаются из следующих ключевых слов:

char int signed

double long unsigned

float short

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

Интегральные типы

Типы char, short, int и long, а также их варианты unsigned называются интегральными типами. Ниже приводятся спецификаторы интегральных типов с помещенными в той же строке синонимами.

Интегральные типы Таблица 1.14

char,signed char Если по умолчанию char установлен как signed, то это синонимы

unsigned char

char,unsigned char Если по умолчанию char установлен как

unsigned, то это синонимы

signed char

int,signed int

unsigned,unsigned int

short,short int,signed short int

unsigned short,unsigned short int

long,long int,signed long int

unsigned long,unsigned long int

С типами char,short, int или long можно использовать либо signed, либо unsigned. Если же использовать только сами ключевые слова signed или unsigned, то они означают signed int или unsigned int, соответственно.

В отсутствие слова unsigned обычно принимается тип signed. Исключение возникаетв случае char. Turbo C++ позволяет устанавливатьдля char умолчание signed или unsigned. (Если вы не устанавливали это умолчание сами, то это умолчание будет равно signed). Если умолчание установлено в значение unsigned, то объявление char ch объявит ch как unsigned. Для переопределение этогоумолчания нужно задать signed char ch. Аналогичным образом, если для char установлено умолчание signed, то для объявления ch как unsigned char следует явно указать unsigned char ch.

С int можно использовать либо long, либо short. Если ключевые словаlong или short использованы сами по себе, то они означают long int или short int, соответственно.

ANSI C не устанавливаетразмеры внутреннего представления этих типов, за исключением того, что размеры данных short, int и long образуют неубывающую последовательность"short <= int <= long". Все три типа могут быть одинаковыми. Это существенно для написания мобильных кодов, предназначенных для переноса на другую аппаратную базу.

В Turbo C++ типы int и short эквивалентны, и имеют оба длину 16 бит. long представляет 32-битовые объекты. Их разновидность с ключевым словом signed хранятся вформате дополнения до двух, причем в качестве знакового бита используется MSB (наиболее значащий бит): 0 означает положительное число, 1 - отрицательное (что объясняет диапазоне, приведенные в таблице 1.9). В версиях unsigned дляхранения числа используются все биты, что дает диапазон 0-(2^n-1), где n = 8,16 или

32.

Типы с плавающей точкой

Представления и множества принимаемых значений для типов с плавающей точкой зависят от конкретной реализации; то есть каждая новая реализация компилятора С свободна определять их по-своему. TurboC++ использует форматы с плавающей точкой IEEE. (Приложение А, "Стандарты ANSI, зависимые от реализации" содержит более подробную информацию по этому вопросу.)

float иdoubleпредставляют собой 32- и 64-разрядные типы данных с плавающей точкой, соответственно. long можно использовать с double для получения 80-разрядной точности представления идентификатора с плавающей точкой: long double test_case, например.

Распределяемая для типов с плавающей точкой память показана в таблице 1.9.

Стандартные преобразования

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

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

1. Все малые интегральные типы преобразовываются согласно таблице 1.15. После этого любые два значения, участвующие в операции, становятся либо Int (включая модификаторы long и unsigned), либо double, float или long double.

2. Если один из операндов имеет тип long double, то второй операнд также будет преобразован к типу long double.

3. Иначе, если один из операндов имеет тип double, то второй операнд также будет преобразован к типу double.

4. Иначе, если один из операндов имеет тип float, то второй операнд также будет преобразован к типу float.

5. Иначе, если один из операндов имеет тип unsigned long, то второй операнд также будет преобразован к типу unsigned long.

6. Иначе, если один из операндов имеет тип long, то второй операнд также будет преобразован к типу long.

7. Иначе, если один из операндов имеет тип unsigned, то второй операнд также будет преобразован к типу unsigned.

8. В противном случае оба операнда имеют тип Int.

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

Методы стандартных арифметических преобразований Таблица 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, если что указатель

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

Синтаксис инициализаторов следующий: инициализатор

= выражение

= (*список-инициализаторов*)<,>*)

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

список-инициализаторов

выражение

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

(*список-инициализаторов*)<,>*)

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

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

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

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

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

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

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

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

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

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

- списком инициализаторов, как описано в следующем разделе

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

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

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

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

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

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

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 <=иниц1>, перем2 <=иниц2>,...;

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

int x = 1, y = 2;

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

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

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

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

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

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

auto register typedef

extern static

Использование спецификатора класса памяти 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 в качестве спецификаторановоготипа, не создавая при этомкакого-либо объекта времени выполнения. 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 оригинала).

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

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

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

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

void (*func)();

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

void(*func)(int);

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

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

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

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

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

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

объявит 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; // Присвоение константы-указателя-на

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

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

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

Вычитание междудвумя указателями на элементы одного и того же массива дает интегральное значение типа 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".

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

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

Массивы

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

Объявление

type декларатор [<выражение-типа-константы>]

объявляет масив, состоящий из элементов типа type. Массив в С состоит из непрерывной области памяти, по размеру позволяющей в точности разместить все его элементы.

Если в деклараторе массива задано выражение, то при еговычислении должна получаться положительная целочисленная константа. Получившееся значение представляет собой число элементов массива. Каждый из элементовмассива нумеруется от 0 до числа элементов массива, минус единица.

Многомерные массивы создаются путем объявления массивов из элементов типа массив. Таким образом, двумерный массив из пяти строк и семи столбцов с именем alpha объявляется следующим образом:

type alpha [5] [7];

В определенном контексте первый декларатор массива из нескольких может не иметь выражения в квадратных скобках. Такой массив имеет неопределенный размер. Контекстом, где допустимо такое положение, является тот случай, когдадля резервирования памяти размер массива не требуется. Например, для объявление объекта типа массива extern точный размер массива не требуется; не требуется он и при передаче функции параметра типа массива. Будучи специальным расширением ANSI C, Turbo C также позволяет объявлятьв качестве последнего элемента структуры массив неопределенного размера. Такой массив не увеличивает размера структуры, а для того, чтобы обеспечить правильное выравнивание структуры, ее можно специально дополнить символами-заполнителями. Такие структуры обычно используются при динамическом распределении памяти, когда для правильного резервирования области памяти к размеру структуры следует явно прибавить фактический размер необходимого массива.

За исключением использования массива в качестве операнда операции sizeof или &, выражение с типом массива преобразуется в константу-указатель на первый элемент массива.

Функции

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

Объявления и определения

Каждая программа должна иметь одну внешнюю функцию main, содержащую точку входа в программу. Обычно функции объявляютсякак прототипы в стандартных или создаваемых пользователем файлах заголовка, либо в файлах программы. По умолчанию функции имеют тип extern, и доступ к ним возможен из любого файла программы. Функция может быть ограничена спецификатором класса памяти static (см. стр. 32 оригинала).

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

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

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

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

Объявления и прототипы

В оригинальном стиле объявлений Кернигэна и Ритчи функция могла быть либо объявлена неявно, по ее вызову, либо явно:

<type> func()

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

Эта задача упрощается благодаря введению прототипа функции со следующим синтаксисом объявления:

<type> func(список-деклараторов-параметров)

При помощи IDE или опции компилятора командной строки можно разрешить выдачу следующего предупреждения: "Function called without a prototype" ("Функция вызывается без прототипа").

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

long lmax(long v1, long v2); /* прототип */

main()

(*

int limit = 32;

char ch = 'A';

long mval;

mval = lmax(limit,ch): /* вызов функции */

Поскольку данная программа имеет прототип функции для lmax, данная программа преобразовывает limit и ch к типу long по стандартным правилам присвоения, прежде чем поместить их в стекдля вызова lmax.Без прототипа функции limit и ch были бы помещены в стек как целое и символьное значения, соответственно; в этом случае стек, переданный lmax, не соответствовал бы по размеру и содержимому тому, что ожидает на входе lmax, что привело бы к возникновению проблем. Классический стиль объявлений не позволяет выполнять контроль типа и числа параметров, поэтому использование прототипов функций существенно упрощает отслеживаниепрограммных ошибок.

Прототипы функций также упрощают документирование кодов программы. Например, функция strcpy принимает два параметра: исходную строку и строку назначения. Вопрос, где какая из них? Прототип функции

char *strcpy(char *dest, char *source);

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

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

func(void);

В С++ func() также означает функцию, не принимающую аргументов.

stdarg.h содержит макросы, которые можно использовать в функциях, определяемых пользователем, с переменным числом параметров.

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

f(int *const, long total, ...)

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

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

int f(); /* В С это функция, возвращащая int, без информации о параметрах. Это "классический стиль" Кернигэна и Ритчи */

int f(); /* В С++ это функция, не принимающая аргументов */

int f(void); /* Функция, возвращающая int и не принимающая параметров */

int p(int,long) /* Функция с типомвозврата int,принимающая два параметра, первый типа int, и второй типа long */

int pascal q(void); /* функция типа pascal, возвращающая int и не принимающая параметров */

char far *s(char *source, int kind); /* Функция, возвращающая дальний указатель на char и принимающая два параметра: превый - дальний указатель на char, а второй int */

int printf(char *format,...); /* Функция, возвращающая int и принимающая фиксированный параметр типа указатель на char и любое число дополнительных параметров неизвестного типа */

int (*fp)(int); /* Указатель на функцию, возвращающую int и принимающую один параметр int */

Объявления

Общий синтаксис для определений внешних функций приводится в следующей таблице:

Определения внешних функций Таблица 1.18

файл:

внешнее-определение

файл внешнее-определение

внешнее-определение:

определение-функции

объявление

asm-оператор

определение-функции:

<спецификаторы-объявления> декларатор <список-объявления>

составной-оператор

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

1. Опциональные спецификаторы класса памяти: extern или static. Умолчанием является extern.

2. Тип возврата, возможно void. Умолчанием является int.

Элементы из пунктов 1 и 2 можно взаимно комбинировать.

3. Опциональные модификаторы: pascal, cdecl, interrupt, near, far, huge. Умолчание зависит от модели памяти и установленных опций компилятора.

4. Имя функции.

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


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

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

Скачать
14945
0
7

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

Скачать
225728
6
0

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

Скачать
49224
0
9

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

Скачать
132529
1
5

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

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


Наверх