Character literal
Contents |
Syntax
' c-char '
|
(1) | ||||||||
u8' c-char '
|
(2) | (since C++17) | |||||||
u' c-char '
|
(3) | (since C++11) | |||||||
U' c-char '
|
(4) | (since C++11) | |||||||
L' c-char '
|
(5) | ||||||||
' c-char-sequence '
|
(6) | ||||||||
L' c-char-sequence '
|
(7) | ||||||||
c-char | - | either
|
c-char-sequence | - | two or more c-chars |
Explanation
Non-encodable characters
In (1), if c-char is not a numeric character sequence and is not representable as a single byte in the execution character set, the character literal is conditionally supported, has type int and implementation-defined value.
In (2-4), if c-char is not a numeric character sequence and cannot be represented as a single code unit in the associated character encoding, the character literal is ill-formed.
In (5), if c-char is not a numeric character sequence and is not representable as a single code unit in the execution wide character set (e.g. a non-BMP value on Windows where wchar_t is 16-bit), the character literal is conditionally supported, has type wchar_t and implementation-defined value.
Numeric escape sequences
Numeric (octal and hexadecimal) escape sequences can be used for specifying the value of the character.
If the character literal contains only one numeric escape sequence, and the value specified by the escape sequence is representable by the unsigned version of its type, the character literal has the same value as the specified value (possibly after conversion to the character type). A UTF-N character literal can have any value representable by its type. If the value does not correspond to a valid Unicode code point, or if the its corresponding code point is not representable as single code unit in UTF-N, it can still be specified by a numeric escape sequence with the value. E.g. u8'\xff' is well-formed and equal to char8_t(0xFF). |
(since C++23) |
If the value specified by a numeric escape sequence used in a ordinary or wide character literal is not representable by char or wchar_t respectively, the value of the character literal is implementation-defined. |
(until C++23) |
If the value specified by a numeric escape sequence used in a ordinary or wide character literal with one c-char is representable by the unsigned version of the underlying type of char or wchar_t respectively, the value of the literal is the integer value of that unsigned integer type and the specified value converted to the type of the literal. Otherwise, the program is ill-formed. |
(since C++23) |
If the value specified by a numeric escape sequence used in a UTF-N character literal is not representable by the corresponding |
(since C++11) |
Notes
Multicharacter literals were inherited by C from the B programming language. Although not specified by the C or C++ standard, most compilers (MSVC is a notable exception) implement multicharacter literals as specified in B: the values of each char in the literal initialize successive bytes of the resulting integer, in big-endian zero-padded right-adjusted order, e.g. the value of '\1' is 0x00000001 and the value of '\1\2\3\4' is 0x01020304.
In C, character constants such as 'a' or '\n' have type int, rather than char.
Example
#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; } int main() { print("literal hex dump \n" "─────── ───────────\n"); dump("a", 'a'); dump("🍌", '🍌'); // implementation-defined print("\n"); // ordinary multi-character literal dump("ab", 'ab'); // implementation-defined print("\n"); // UTF-16 character literals char16_t uc1 = u'a'; dump("a", uc1); char16_t uc2 = u'¢'; dump("¢", uc2); char16_t uc3 = u'猫'; dump("猫", uc3); // char16_t uc4 = u'🍌'; dump("🍌", uc4); // error: 🍌 maps to two UTF-16 code units print("\n"); // UTF-32 character literals char32_t Uc1 = U'a'; dump("a", Uc1); char32_t Uc2 = U'¢'; dump("¢", Uc2); char32_t Uc3 = U'猫'; dump("猫", Uc3); char32_t Uc4 = U'🍌'; dump("🍌", Uc4); print("\n"); // wide character literals wchar_t wc1 = L'a'; dump("a", wc1); wchar_t wc2 = L'¢'; dump("¢", wc2); wchar_t wc3 = L'猫'; dump("猫", wc3); wchar_t wc4 = L'🍌'; dump("🍌", wc4); }
Possible output:
literal hex dump ─────── ─────────── 'a' 61 '🍌' 8C 8D 9F F0 'ab' 62 61 00 00 'a' 61 00 '¢' A2 00 '猫' 2B 73 'a' 61 00 00 00 '¢' A2 00 00 00 '猫' 2B 73 00 00 '🍌' 4C F3 01 00 'a' 61 00 00 00 '¢' A2 00 00 00 '猫' 2B 73 00 00 '🍌' 4C F3 01 00
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 912 | C++98 | non-encodable ordinary character literal was unspecified | specified as conditionally-supported |
CWG 1024 | C++98 | multicharacter literal were required to be supported | made conditionally-supported |
CWG 1656 | C++98 | meaning of numeric escape sequence in a character literal is unclear | specified |
See also
user-defined literals(C++11) | literals with user-defined suffix |
C documentation for Character constant
|