Литералы
В С++ имеется набор встроенных типов данных для представления целых и вещественных чисел, символов, а также тип данных “символьный массив”, который служит для хранения символьных строк. Тип char служит для хранения отдельных символов и небольших целых чисел. Он занимает один машинный байт. Типы short, int и long предназначены для представления целых чисел. Эти типы различаются только диапазоном значений, которые могут принимать числа, а конкретные размеры перечисленных типов зависят от реализации. Обычно short занимает половину машинного слова, int– одно слово, long – одно или два слова. В 32-битных системах int и long, как правило, одного размера.
Типы float, double и long double предназначены для чисел с плавающей точкой и различаются точностью представления (количеством значащих разрядов) и диапазоном. Обычно float (одинарная точность) занимает одно машинное слово, double (двойная точность) – два, а long double (расширенная точность) – три.
char, short, int и long вместе составляют целые типы, которые, в свою очередь, могут быть знаковыми
(signed) и беззнаковыми (unsigned). В знаковых типах самый левый бит служит для хранения знака (0 – плюс, 1 – минус), а оставшиеся биты содержат значение. В беззнаковых типах все биты используются для значения. 8-битовый тип signed char может представлять значения от -128 до 127, а unsigned char – от 0 до 255.
Когда в программе встречается некоторое число, например 1, то это число называется литералом, или литеральной константой. Константой, потому что мы не можем изменить его значение, и литералом, потому что его значение фигурирует в тексте программы. Литерал является неадресуемой величиной: хотя реально он, конечно, хранится в памяти машины, нет никакого способа узнать его адрес. Каждый литерал имеет определенный тип. Так, 0 имеет тип int, 3.14159 – тип double.
Литералы целых типов можно записать в десятичном, восьмеричном и шестнадцатеричном виде. Вот как выглядит число 20, представленное десятичным, восьмеричным и шестнадцатеричным литералами:
20 // десятичный
024 // восьмеричный
0х14 // шестнадцатеричный
Если литерал начинается с 0, он трактуется как восьмеричный, если с 0х или 0Х, то как шестнадцатеричный. Привычная запись рассматривается как десятичное число.
По умолчанию все целые литералы имеют тип signed int. Можно явно определить целый литерал как имеющий тип long, приписав в конце числа букву L (используется как прописная L, так и строчная l, однако для удобства чтения не следует употреблять строчную: ее легко перепутать с 1). Буква U (или u) в конце определяет литерал как unsigned int, а две буквы – UL или LU – как тип unsigned long. Например:
128u 1024UL 1L 8Lu
Литералы, представляющие действительные числа, могут быть записаны как с десятичной точкой, так и в научной (экспоненциальной) нотации. По умолчанию они имеют тип double. Для явного указания типа float нужно использовать суффикс F или f, а для long double - L или l, но только в случае записи с десятичной точкой. Например:
3.14159F 0/1f 12.345L 0.0
3el 1.0E-3E 2. 1.0L
Слова true и false являются литералами типа bool.
Представимые литеральные символьные константы записываются как символы в одинарных кавычках. Например:
'a' '2' ',' ' ' (пробел)
Специальные символы (табуляция, возврат каретки) записываются как escape-последовательности . Определены следующие такие последовательности (они начинаются с символа обратной косой черты):
новая строка \n
горизонтальная табуляция \t
забой \b
вертикальная табуляция \v
возврат каретки \r
прогон листа \f
звонок \a
обратная косая черта \\
знак вопроса \?
одиночная кавычка \'
двойная кавычка \"
escape-последовательность общего вида имеет форму \ooo, где ooo – от одной до трех восьмеричных цифр. Это число является кодом символа. Используя ASCII-код, мы можем написать следующие литералы:
\7 (звонок) \14 (новая строка)
\0 (null) \062 ('2')
Символьный литерал может иметь префикс L (например, L'a'), что означает специальный тип wchar_t – двухбайтовый символьный тип, который применяется для хранения символов национальных алфавитов, если они не могут быть представлены обычным типом char, как, например, китайские или японские буквы.
Строковый литерал – строка символов, заключенная в двойные кавычки. Такой литерал может занимать и несколько строк, в этом случае в конце строки ставится обратная косая черта. Специальные символы могут быть представлены своими escape-последовательностями. Вот примеры строковых литералов:
"" (пустая строка)
"a"
"\nCC\toptions\tfile.[cC]\n"
"a multi-line \
string literal signals its \
continuation with a backslash"
Фактически строковый литерал представляет собой массив символьных констант, где по соглашению языков С и С++ последним элементом всегда является специальный символ с кодом 0 (\0).
Литерал 'A' задает единственный символ А, а строковый литерал "А" – массив из двух элементов: 'А' и \0 (пустого символа).
Раз существует тип wchar_t, существуют и литералы этого типа, обозначаемые, как и в случае с отдельными символами, префиксом L:
L"a wide string literal"
Строковый литерал типа wchar_t – это массив символов того же типа, завершенный нулем.
Если в тесте программы идут подряд два или несколько строковых литералов (типа char или wchar_t), компилятор соединяет их в одну строку. Например, следующий текст
"two" "some"
породит массив из восьми символов – twosome и завершающий нулевой символ. Результат конкатенации строк разного типа не определен. Если написать:
// this is not a good idea
"two" L"some"
то на каком-то компьютере результатом будет некоторая осмысленная строка, а на другом может оказаться нечто совсем иное. Программы, использующие особенности реализации того или иного компилятора или операционной системы, являются непереносимыми. Мы крайне не рекомендуем пользоваться такими конструкциями.
Упражнение 3.1
Объясните разницу в определениях следующих литералов:
(a) 'a', L'a', "a", L"a"
(b) 10, 10u, 10L, 10uL, 012, 0*C
(c) 3.14, 3.14f, 3.14L
Упражнение 3.2
Какие ошибки допущены в приведенных ниже примерах?
(a) "Who goes with F\144rgus?\014"
(b) 3.14e1L
(c) "two" L"some"
(d) 1024f
(e) 3.14UL
(f) "multiple line
comment"