Литерал — значение, записанное прямо в тексте программы. У него уже есть тип, ещё до того как значение попадёт в переменную.

Целые числа и системы счисления

123        // десятичное: 123
0123       // восьмеричное: 83
0x123      // шестнадцатеричное: 291
0b101      // двоичное: 5

Ведущий ноль — не украшение и не выравнивание: 0123 и 123 это разные числа. Ошибка живучая, потому что выглядит как форматирование. После 0b допустимы только двоичные цифры, 0b123 корректным литералом не является.

Апостроф разделяет разряды и на значение не влияет:

2'000'000'000 == 2000000000   // true

Полезно там, где ошибка в количестве нулей меняет смысл.

Тип целого литерала

Для десятичного литерала без суффикса выбирается первый подходящий тип из последовательности int, long, long long. Поэтому 10 имеет тип int, а тип достаточно большого литерала зависит от платформы:

std::cout << (10 + 3'000'000'000) << '\n';   // 3000000010

Здесь 3'000'000'000 в int не помещается, и на 64-битном Linux его типом становится long. Переполнения нет — просто литерал оказался шире, чем кажется.

Суффиксы

10      // int              0.1     // double
10U     // unsigned int     0.1F    // float
10L     // long             0.1L    // long double
10LL    // long long
10UL    // unsigned long
10ULL   // unsigned long long

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

Суффикс — не косметика. Выражение вычисляется в типах операндов, а не в типе переменной слева:

long long a = 1000000 * 1000000;    // умножение в int → UB
long long b = 1000000LL * 1000000;  // 1000000000000

См. Арифметические преобразования типов и Неопределённое поведение.

У short собственного суффикса нет. Запись short x = 1; создаёт переменную типа short, но литерал 1 остаётся литералом типа int и преобразуется при инициализации.

Суффикса lf не существует

В комментариях к коду занятия встречается 0.1lf. Это спецификатор формата из printf, а не суффикс литерала C++. Для long double суффикс L.

Остальные литералы

3.14        // дробный
1.23e-10    // 1.23 * 10^(-10)
'v'         // символьный
"Hello"     // строковый
true        // логический
false       // логический
nullptr     // нулевой указатель

Одинарные и двойные кавычки не взаимозаменяемы. 'v' — символ типа char, "v" — строковый литерал; у них разные типы и разное представление в памяти. Строковый литерал хранится с завершающим нулевым байтом, поэтому sizeof("A\0B") равен 4, а sizeof('A') — 1. См. Символьный тип char.

Тонкости

  • Тип литерала определяется до всякой арифметики, поэтому исправлять переполнение надо суффиксом или static_cast у операнда, а не типом переменной слева.
  • double x = 0.0f; компилируется, но врёт читателю: литерал создаётся как float и расширяется до double.
  • Для дробного литерала без суффикса тип всегда double, а не float.
  • Числовые литералы не бывают отрицательными: в -5 минус это унарная операция над литералом 5. Обычно незаметно, но важно на границе диапазона.

Частые ошибки

  • Выровнять числа нулями и получить восьмеричные значения.
  • Забыть суффикс при работе с большими числами.
  • Писать l вместо L и потом читать 10l как «десять-один».
  • Путать '0' (символ, код 48) и 0 (число).