Пространства имён
Варианты
Действия

Символьный литерал

Материал из cppreference.com
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++17*)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определяемые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Types
Объявление typedef
Объявление псевдонима типа (C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
explicit (C++11)
static
Специальные функции-элементы
Шаблоны
Разное
 
Выражения
Общие
Категории значений (lvalue, rvalue, xvalue)
Порядок оценки (точки последовательности)
Константные выражения
Потенциально оцениваемые выражения
Первичные выражения
Лямбда-выражения(C++11)
Литералы
Целочисленные литералы
Литералы с плавающей запятой
Логические литералы
Символьные литералы, включая управляющие последовательности
Строковые литералы
Литерал нулевого указателя(C++11)
Пользовательский литерал(C++11)
Операторы
a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b
++a, --a, a++, a--
+a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b
a||b, a&&b, !a
a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b (начиная с C++20)
a[b], *a, &a, a->b, a.b, a->*b, a.*b
a(...), a,b, a?b:c
выражение new
выражение delete
выражение throw
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
Выражения свёртки(C++17)
Альтернативные представления операторов
Приоритет и ассоциативность
Перегрузка операторов
Сравнение по умолчанию(C++20)
Преобразования
Неявные преобразования
Обычные арифметические преобразования
const_cast
static_cast
reinterpret_cast
dynamic_cast
Явные преобразования: (T)a, T(a), auto(a), auto{a} (начиная с C++23)
Пользовательское преобразование
 

Синтаксис

'c-символ  ' (1)
u8'c-символ  ' (2) (начиная с C++17)
u'c-символ  ' (3) (начиная с C++11)
U'c-символ  ' (4) (начиная с C++11)
L'c-символ  ' (5)
'последовательность-c-символов  ' (6)
L'последовательность-c-символов  ' (7)
c-символ одно из
базовый-c-символ Символ из исходного набора символов (до C++23)набора символов трансляции (начиная с C++23), за исключением одиночной кавычки ', обратной косой черты \ или символа новой строки
последовательность-c-символов два или более c-символа

Объяснение

1) Обычный символьный литерал, например 'a' или '\n' или '\13'. Такой литерал имеет тип char и значение, равное представлению c-символа в в наборе символов выполнения (до C++23)соответствующей кодовой точке из обычной литеральной кодировки (начиная с C++23).
2) Символьный литерал UTF-8, например u8'a'. Такой литерал имеет тип char (до C++20)char8_t (начиная с C++20) и значение, равное значению кодовой точки ISO 10646 c-символа, при условии, что значение кодовой точки может быть представлено с помощью одной кодовой единицы UTF-8 (то есть, c-символ находится в диапазоне 0x0-0x7F включительно).
3) Символьный литерал UTF-16, например u'猫', но не u'🍌' (u'\U0001f34c'). Такой литерал имеет тип char16_t и значение, равное значению кодовой точки ISO 10646 c-символа, при условии, что значение кодовой точки может быть представлено одной кодовой единицей UTF-16 (что есть c-символ в диапазоне 0x0-0xFFFF, включительно).
4) Символьный литерал UTF-32, например U'猫' или U'🍌'. Такой литерал имеет тип char32_t и значение, равное значению кодовой точки ISO 10646 c-символа.
5) Литерал широкого символа, например L'β' или L'猫'. Такой литерал имеет тип wchar_t и значение, равное значению c-символа в наборе широких символов выполнения (до C++23)соответствующей кодовой точки из широкой литеральной кодировки (начиная с C++23).
6) Обычный многосимвольный литерал, например 'AB', поддерживается условно, имеет тип int и значение, определяемое реализацией.
7) Широкий многосимвольный литерал, например L'AB', поддерживается условно, имеет тип wchar_t и значение, определяемое реализацией.

Некодируемые символы

1-5) Учитывая, что c-символ не является числовой управляющей последовательностью (смотрите ниже), если c-символ не может быть представлен в связанной с литералом кодировке символов или не может быть закодирован как одна кодовая единица в этой кодировке (например, значение, отличное от BMP в Windows, где wchar_t 16-битное), программа некорректна.
6) Если какой-либо c-символ в последовательности-c-символов не может быть закодирован как одна кодовая единица в обычном литеральном кодировании, программа некорректна.
7) Если какой-либо c-символ в последовательности-c-символов не может быть закодирован как одна кодовая единица в широком литеральном кодировании, программа некорректна.
(до C++23)

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

Числовые (восьмеричные и шестнадцатеричные) управляющие последовательности могут использоваться для указания значения символа.

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

Символьный литерал UTF-N может иметь любое значение, представляемое его типом. Если значение не соответствует действительной кодовой точке Юникода или если соответствующая ей кодовая точка не может быть представлена как одиночная кодовая единица в UTF-N, её все равно можно указать числовой управляющей последовательностью со значением. Например u8'\xff' имеет правильный формат и равна char8_t(0xFF).

(начиная с C++23)


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

(до C++23)

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

(начиная с C++23)


Если значение, заданное числовой управляющей последовательностью, используемой в символьном литерале UTF-N, не может быть представлено соответствующим charN_t, значение символьного литерала определяется реализацией (до C++17)программа имеет неправильный формат (начиная с C++17).

(начиная с C++11)

Примечание

Многосимвольные литералы были унаследованы C от языка программирования B. Хотя это и не указано в стандарте C или C++, большинство компиляторов (за исключением MSVC) реализуют многосимвольные литералы, как указано в B: значения каждого символа в литерале инициализируют последовательные байты результирующего целого числа от старшего к младшему, дополненного нулями, скорректированному вправо порядке, например, значение '\1' равно 0x00000001, а значение '\1\2\3\4' равно 0x01020304.

В C символьные константы, такие как 'a' или '\n', имеют тип int, а не char.

Пример

#include <cstdint>
#include <iomanip>
#include <iostream>
#include <string_view>

template <typename CharT>
void dump(std::string_view s, const CharT c) {
    const uint8_t* data {reinterpret_cast<const uint8_t*>(&c)};
    std::cout << s << " \t" << std::hex
              << std::uppercase << std::setfill('0');
    for (auto i {0U}; i != sizeof(CharT); ++i){
        std::cout << std::setw(2) << static_cast<unsigned>(data[i]) << ' ';
    }
    std::cout << '\n';
}

void print(std::string_view str = "") { std::cout << str << '\n'; }

int main()
{
    print("Литералы обычных символов:");
    char c1 = 'a'; dump("'a'", c1);
    char c2 = '\x2a'; dump("'*'", c2);

    print("\n" "Обычные многосимвольные литералы:");
    int mc1 = 'ab'; dump("'ab'", mc1);  	// определено реализацией
    int mc2 = 'abc'; dump("'abc'", mc2);	// определено реализацией

    print("\n" "Символьные литералы UTF-8:");
    char8_t C1 = u8'a'; dump("u8'a'", C1);
//  char8_t C2 = u8'¢'; dump("u8'¢'", C2);	// ошибка: ¢ сопоставляется с двумя
                                                // кодовыми единицами UTF-8
//  char8_t C3 = u8'猫'; dump("u8'猫'", C3);	// ошибка: 猫 сопоставляется с тремя
                                                // кодовыми единицами UTF-8
//  char8_t C4 = u8'🍌'; dump("u8'🍌'", C4);	// ошибка: 🍌 сопоставляется с четырьмя
                                                // кодовыми единицами UTF-8

    print("\n" "Символьные литералы UTF-16:");
    char16_t uc1 = u'a'; dump("u'a'", uc1);
    char16_t uc2 = u'¢'; dump("u'¢'", uc2);
    char16_t uc3 = u'猫'; dump("u'猫'", uc3);
//  char16_t uc4 = u'🍌'; dump("u'🍌'", uc4); 	// ошибка: 🍌 сопоставляется с двумя
                                                // кодовыми единицами UTF-16

    print("\n" "Символьные литералы UTF-32:");
    char32_t Uc1 = U'a'; dump("U'a'", Uc1);
    char32_t Uc2 = U'¢'; dump("U'¢'", Uc2);
    char32_t Uc3 = U'猫'; dump("U'猫'", Uc3);
    char32_t Uc4 = U'🍌'; dump("U'🍌'", Uc4);

    print("\n" "Литералы широких символов:");
    wchar_t wc1 = L'a'; dump("L'a'", wc1);
    wchar_t wc2 = L'¢'; dump("L'¢'", wc2);
    wchar_t wc3 = L'猫'; dump("L'猫'", wc3);
    wchar_t wc4 = L'🍌'; dump("L'🍌'", wc4);
}

Возможный вывод:

Литералы обычных символов:
'a' 	61 
'*' 	2A 

Обычные многосимвольные литералы:
'ab' 	62 61 00 00
'abc' 	63 62 61 00

Символьные литералы UTF-8:
u8'a' 	61 

Символьные литералы UTF-16:
u'a' 	61 00 
u'¢' 	A2 00 
u'猫' 	2B 73 

Символьные литералы UTF-32:
U'a' 	61 00 00 00 
U'¢' 	A2 00 00 00 
U'猫' 	2B 73 00 00 
U'🍌' 	4C F3 01 00 

Литералы широких символов:
L'a' 	61 00 00 00 
L'¢' 	A2 00 00 00 
L'猫' 	2B 73 00 00 
L'🍌' 	4C F3 01 00

Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
CWG 912 C++98 некодируемый литерал обычного символа не был
специфицирован
специфицирован как условно-поддерживаемый
CWG 1024 C++98 многосимвольный литерал должен был поддерживаться сделан условно-поддерживаемым
CWG 1656 C++98 значение числовой управляющей последовательности
в символьном литерале неясно
специфицировано
WG не указан C++98 некодируемые символьные литералы поддерживались
условно
программа некорректна

Ссылки

  • C++23 стандарт (ISO/IEC 14882:2023):
  • 5.13.3 Символьные литералы [lex.ccon]
  • C++20 стандарт (ISO/IEC 14882:2020):
  • 5.13.3 Символьные литералы [lex.ccon]
  • C++17 стандарт (ISO/IEC 14882:2017):
  • 5.13.3 Символьные литералы [lex.ccon]
  • C++14 стандарт (ISO/IEC 14882:2014):
  • 2.14.3 Символьные литералы [lex.ccon]
  • C++11 стандарт (ISO/IEC 14882:2011):
  • 2.14.3 Символьные литералы [lex.ccon]
  • C++03 стандарт (ISO/IEC 14882:2003):
  • 2.13.2 Символьные литералы [lex.ccon]
  • C++98 стандарт (ISO/IEC 14882:1998):
  • 2.13.2 Символьные литералы [lex.ccon]

Смотрите также

определяемые пользователем литералы(C++11) литералы с пользовательским суффиксом[править]
Документация C по Символьная константа