Константа это — значение, которое постоянно во время компиляции, и
часто представляют из себя число, символ или стринг. Каждая константа имеет
тип, определяемый её формой и значением. Например, значение 1 может иметь тип
signed int
, а значение 400000 — signed long
.
Во многих случаях тип константы не имеет большого значения. Если, например,
значение 1 присваивается объекту типа long int
, то до присвоения
оно будет сконвертировано в длинное целое.
Целая константа начинается с цифры и не содержит десятичной части или экспоненты. Она может начинаться с префикса, который определяет основание константы: восьмеричная, десятичная или шестнадцатеричная.
Константа может заканчиваться суффиксом u
или u
,
что значит unsigned int
, или l
или l
— long 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) |
\x hh |
шестнадцатеричное значение | \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
.
Как показано выше, расширенные стринговые литералы могут также содержать однобайтовые символы, так как расширенный символьный набор содержит их в себе. Однобайтовые символы преобразуются в соответствующие расширенные коды.
Компилятор объединяет идущие подряд расширенные стринговые литералы и добавляет в конец нулевой символ. Если объединяется стринговый литерал и расширенный стринговый литерал, то поведение компилятора при этом не определено.