Содержание

Константы

Константа это — значение, которое постоянно во время компиляции, и часто представляют из себя число, символ или стринг. Каждая константа имеет тип, определяемый её формой и значением. Например, значение 1 может иметь тип signed int, а значение 400000 — signed long. Во многих случаях тип константы не имеет большого значения. Если, например, значение 1 присваивается объекту типа long int, то до присвоения оно будет сконвертировано в длинное целое.

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

Целая константа начинается с цифры и не содержит десятичной части или экспоненты. Она может начинаться с префикса, который определяет основание константы: восьмеричная, десятичная или шестнадцатеричная.

Константа может заканчиваться суффиксом u или u, что значит unsigned int, или l или llong int, или обоими — unsigned long int.

Если константа начинается не с нуля и содержит последовательность цифр, то она интерпретируется как десятичная (по основанию 10). Примеры десятичных констант:

7
762
98765L

Если константа начинается с 0x или с 0X, за которыми следуют цифры от 0 до 9 и буквы от a (англ.) (или A) до f (или F), то она интерпретируется как шестнадцатеричная (по основанию 16). Буквы от A до F представляют значения от 10 до 15 соответственно. Примеры шестнадцатеричных констант:

0X07FFF
0x12345678L
0xFABE

Если константа начинается с нуля, то это — восьмеричная константа и может содержать цифры от 0 до 7. Примеры восьмеричных констант:

017
0735643L
0

Помните, что константа 0 на самом деле — восьмеричная, но она — нуль и в десятичной, и в восьмеричной, и в шестнадцатеричной системе.

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

Константа Тип
десятичная без суффикса int, long, unsigned long
восьмеричная без суффикса int, unsigned int, long, unsigned long
шестнадцатеричная без суффикса int, unsigned int, long, unsigned long
только суффикс U unsigned int, unsigned long
только суффикс L long, unsigned long
суффиксы U и L unsigned long

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

Константа Десятичное
значение
Шестнадцатеричное
значение
Тип Watcom C/16 Тип Watcom C/32
33 33 21 signed int signed int
033 27 1B signed int signed int
0x33 51 33 signed int signed int
33333 33333 8235 signed long signed int
033333 14043 36DB signed int signed int
0xA000 40960 A000 unsigned int signed int
0x33333 209715 33333 signed long signed int
0x80000000 2147483648 80000000 unsigned long unsigned int
2147483648 2147483648 80000000 unsigned long unsigned int
4294967295 4294967295 FFFFFFFF unsigned long unsigned int

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

Константу с плавающей точкой можно распознать по наличию либо точки, либо буквы e или e (англ.), либо обе сразу. Она состоит из мантиссы, за которой следует не обязательная экспонента. Мантисса может включать последовательность цифр представляющих целую часть, потом точку, а за ней последовательность цифр — дробную часть. Экспонента должна начинаться с буквы e или e, за которой следует необязательный знак (+ или -) и последовательность цифр, которые вместе со знаком представляют степень 10, на которую нужно умножить мантиссу. При необходимости можно добавить суффикс f или f, чтобы указать, что константа имеет тип float, или суффикс l или l, чтобы указать, что константа — long double. Если суффикса нет, то константа имеет тип double.

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

В таблице ниже приводятся примеры констант с плавающей точкой и их тип:

Константа Значение Тип
3.14159265 3.14159265E0 double
11E24 1.1E25 double
.5L 5E-1 long double
7.234E-22F 7.234E-22 float
0. 0E0 double

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

Символьная константа обычно — один символ заключённый в одиночные кавычки и представляет собой константу, чьё значение является представлением символа в наборе времени исполнения. Символьная константа имеет тип int.

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

Символ Имя символа Эскейп-последовательность
' одиночная кавычка \'
" двойная кавычка " или \"
? знак вопроса ? или \?
\ обратная косая черта \\
\ooo восьмеричное значение \восьмеричные цифры (до 3)
\xhh шестнадцатеричное значение \xшестнадцатеричные цифры

Например,

'a'     /* буква a */
'\''    /* одиночная кавычка */
'?'     /* знак вопроса */
'\?'    /* знак вопроса */
'\\'    /* обратная косая черта */

все являются простыми символьными константами.

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

'\0'
'\377'
'\100'

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

'\1000'
'\109'

первая константа состоит из двух символов — '\100' и '0' (т.к. восьмеричное значение состоит не более, чем из трёх цифр). Вторая константа также состоит из двух символов — '\10' и '9' (т.к. 9 не является восьмеричной цифрой).

Если нужно указать более, чем одно восьмеричное значение символьной константы, то каждое значение нужно указывать начиная с \.

Значение символьной константы с более, чем одним символом зависит от реализации.

Ниже приводятся несколько символьных констант содержащих шестнадцатеричные эскейп-последовательности, полученные при помощи символов \x, за которыми следуют одна или более шестнадцатеричная цифра (цифры от 0 до 9 и буквы от a до f или от a до f). (Их значения те же, что и в первом примере для восьмеричных значений.)

'\x0'
'\xFF'
'\x40'

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

'\xFAx'
'\xFx'

первая константа состоит из двух символов — '\xFA' и 'x' (т.к. x не является шестнадцатеричной цифрой). Вторая константа также состоит из двух символов — '\xF' и 'x'.

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

Значение символьной константы с более, чем одним символом зависит от реализации.

Дополнительно к приведённым выше эскейп-последовательностям можно использовать следующие для представления неграфических символов:

Эскейп-
последовательность
Значение
\a Производит звуковой или визуальный эффект
\b Возврат каретки на один символ
\f Перейти к началу следующей страницы
\n Перейти к началу следующей строки
\r Перейти к началу текущей строки
\t Перейти на следующую позицию горизонтальной табуляции
\v Перейти на следующую позицию вертикальной табуляции

Для представления символов отсутствующих на некоторых терминалах можно использовать следующие трёхсимвольные последовательности (триграфы):

Символ Триграф
[ ??(
] ??)
{ ??<
} ??>
| ??!
# ??=
\ ??/
^ ??'
~ ??-

Компиляторы Watcom C/16 и C/32 допускают символьные константы из более, чем одного символа. Они могут использоваться для инициализации больших чем char типов, таких как int. Например, фрагмент программы:

int code;
code = 'ab';

присваивает константное значение 'ab' целому объекту code. Буква b помещается в младшую (менее значащую) часть целого, а буква a — в следующую, более значащую часть.

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

Нужно отметить, что символьная константа (например 'a') не то же самое, что и соответствующий стринговый литерал "a". Первый имеет тип int и является буквой из символьного набора времени исполнения. Второй имеет тип «указатель на char» и его значение — адрес первого символа (a) стрингового литерала.

Расширенные символьные константы

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

Типом расширенной символьной константы является wchar_t, один из целых типов, описанных в заголовочном файле <stddef.h>.

В Watcom C/16 и C/32 wcahr_t определён как unsigned short.

Например, константа L'a' — расширенная символьная константа содержащая букву a из исходного символьного набора и имеющая тип wchar_t. Напротив, константа 'a' является символьной константой содержащей букву a и имеет тип int.

Как многобайтовый символ преобразуется в расширенное символьное значение определено библиотечной функцией mbtowc.

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

Стринговые литералы

Последовательность нуля или более символов заключённая в двойные кавычки называется стринговым литералом.

Большинство правил касающихся создания символьных констант подходят и стринговым литералам. Одиночную кавычку можно вводить как напрямую, так и использование эскейп-последовательности \'. Двойную кавычку необходимо вводить при помощи \".

Значение стрингового литерала — последовательность символов между кавычек плюс нулевой символ в конце.

Тип стрингового литерала — «массив char».

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

"Hello there"
"\"Quotes inside string\""
"G'day"

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

"Hello" "there"

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

"Hellothere"

и будет массивом из 11 символов, включая один закрывающий нулевой символ.

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

"\xFAB\xFA" "B" "\012\01" "2"

первый стринг после объединения состоит из трёх символов со значениями '\xFAB', '\xFA' и 'B'. Второй стринг после объединения также состоит из трёх символов со значениями '\012', '\01' и '2'.

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

Обычно стринговый литерал это — стринг. Это — не стринг, если один из символов внутри двойных кавычек — нулевой символ (\0). Если такой стринговый литерал трактуется как стринг, стрингом будут только те символы, которые располагаются до первого нулевого символа. Все символы после него игнорируются.

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

Компиляторы Watcom C/16 и C/32 заменяют несколько одинаковых стринговых литералов в одном модуле одним, если они встречаются в декларациях константных объектов или командах отличных от деклараций (т.е. присвоении).

Если программе нужно иметь несколько одинаковых стринговых литералов, то нужно декларировать массивы из char, инициализируя их этим стрингом.

Расширенные стринговые литералы

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

Тип расширенного стрингового литерала — «массив из wchar_t», один из целых типов, который объявлен в заголовочном файле <stddef.h>.

В Watcom C/16 и C/32 wchar_t определён как unsigned short.

Например, стринговый литерал L"ab" — расширенный стринговый литерал, содержащий буквы a и b. Его тип — «массив [3] из wchar_t» и значения его элементов — L'a', L'b' и '\0'. В противоположность ему стринговый литерал "ab" имеет тип «массив [3] из char» и значения его элементов — 'a', 'b' и '\0'.

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

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

Компилятор объединяет идущие подряд расширенные стринговые литералы и добавляет в конец нулевой символ. Если объединяется стринговый литерал и расширенный стринговый литерал, то поведение компилятора при этом не определено.