Skip to content

Commit 92c4e74

Browse files
authored
Merge pull request #3742 from corob-msft/docs/corob/zc-char8_t
16.11 Add /Zc:char8_t compiler option
2 parents 727a896 + 6d86e78 commit 92c4e74

6 files changed

Lines changed: 132 additions & 34 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
description: "Learn more about the /Zc:char8_t (Enable C++20 char8_t type) compiler option."
3+
title: "/Zc:char8_t (Enable C++20 char8_t type)"
4+
ms.date: 08/11/2021
5+
f1_keywords: ["/Zc:char8_t"]
6+
helpviewer_keywords: ["-Zc:char8_t compiler option (C++)", "/Zc:char8_t compiler option (C++)"]
7+
---
8+
# `/Zc:char8_t` (Enable C++20 char8_t type)
9+
10+
The **`/Zc:char8_t`** compiler option enables C++20 conforming **`char8_t`** type support. **`char8_t`** is a character type that's used to represent UTF-8 code units.
11+
12+
## Syntax
13+
14+
> **`/Zc:char8_t`**[**`-`**]
15+
16+
## Remarks
17+
18+
The **`/Zc:char8_t`** compiler option enables the **`char8_t`** type keyword as specified in the C++20 standard. It causes the compiler to generate `u8` prefixed character or string literals as `const char8_t` or `const char8_t[N]` types, respectively, instead of as `const char` or `const char[N]` types. In C++17, arrays of **`char`** may be initialized using `u8` string literals. In C++20, this initialization is ill-formed, and causes compiler error [C2440](../../error-messages/compiler-errors-1/compiler-error-c2440.md). This behavior can be a source-breaking change. You can revert the compiler to C++14 or C++17 behavior explicitly by specifying **`/Zc:char8_t-`**.
19+
20+
The **`/Zc:char8_t`** option is available starting in Visual Studio 2019 version 16.1. It's enabled automatically when you specify [`/std:c++20`](std-specify-language-standard-version.md) or later (such as **`/std:c++latest`**). Otherwise, it's off by default.
21+
22+
### Example
23+
24+
```cpp
25+
const char* s = u8"Hello"; // Compiles in C++17, Error C2440 in C++20
26+
const char8_t* s = u8"Hello"; // Compiles in C++20 or with /Zc:char8_t
27+
```
28+
29+
### To set this compiler option in Visual Studio
30+
31+
1. Open the project's **Property Pages** dialog box. For details, see [Set C++ compiler and build properties in Visual Studio](../working-with-project-properties.md).
32+
33+
1. Select the **Configuration Properties** > **C/C++** > **Command Line** property page.
34+
35+
1. Add **`/Zc:char8_t`** or **`/Zc:char8_t-`** to the **Additional options:** pane.
36+
37+
## See also
38+
39+
[`/Zc` (Conformance)](zc-conformance.md)\
40+
[`/std` (Specify language standard version)](std-specify-language-standard-version.md)

β€Ždocs/build/reference/zc-conformance.mdβ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Here are the **`/Zc`** compiler options:
2424
|--|--|
2525
| [`/Zc:alignedNew`](zc-alignednew.md) | Enable C++17 over-aligned dynamic allocation (on by default in C++17). |
2626
| [`/Zc:auto`](zc-auto-deduce-variable-type.md) | Enforce the new Standard C++ meaning for **`auto`** (on by default). |
27+
| [`/Zc:char8_t`](zc-char8-t.md) | Enable or disable C++20 native `u8` literal support as `const char8_t` (off by default, except under **`/std:c++20`**). |
2728
| [`/Zc:__cplusplus`](zc-cplusplus.md) | Enable the `__cplusplus` macro to report the supported standard (off by default). |
2829
| [`/Zc:externConstexpr`](zc-externconstexpr.md) | Enable external linkage for **`constexpr`** variables (off by default). |
2930
| [`/Zc:forScope`](zc-forscope-force-conformance-in-for-loop-scope.md) | Enforce Standard C++ **`for`** scoping rules (on by default). |

β€Ždocs/build/toc.ymlβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@
761761
href: ../build/reference/zc-alignednew.md
762762
- name: "/Zc:auto (Deduce variable type)"
763763
href: ../build/reference/zc-auto-deduce-variable-type.md
764+
- name: "/Zc:char8_t (Enable C++20 char8_t type)"
765+
href: ../build/reference/zc-char8-t.md
764766
- name: "/Zc:__cplusplus (Enable updated __cplusplus macro)"
765767
href: ../build/reference/zc-cplusplus.md
766768
- name: "/Zc:externConstexpr (Enable extern constexpr variables)"

β€Ždocs/cpp/string-and-character-literals-cpp.mdβ€Ž

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "String and character literals (C++)"
33
description: "How to declare and define string and character literals in C++."
4-
ms.date: "02/18/2020"
4+
ms.date: 08/27/2021
55
f1_keywords: ["R", "L", "u", "u8", "LR", "uR", "u8R"]
66
helpviewer_keywords: ["literal strings [C++]", "string literals [C++]"]
77
ms.assetid: 61de8f6f-2714-4e7b-86b6-a3f885d3b9df
@@ -28,28 +28,31 @@ int main()
2828

2929
// String literals
3030
auto s0 = "hello"; // const char*
31-
auto s1 = u8"hello"; // const char*, encoded as UTF-8
31+
auto s1 = u8"hello"; // const char* before C++20, encoded as UTF-8,
32+
// const char8_t* in C++20
3233
auto s2 = L"hello"; // const wchar_t*
3334
auto s3 = u"hello"; // const char16_t*, encoded as UTF-16
3435
auto s4 = U"hello"; // const char32_t*, encoded as UTF-32
3536

3637
// Raw string literals containing unescaped \ and "
3738
auto R0 = R"("Hello \ world")"; // const char*
38-
auto R1 = u8R"("Hello \ world")"; // const char*, encoded as UTF-8
39+
auto R1 = u8R"("Hello \ world")"; // const char* before C++20, encoded as UTF-8,
40+
// const char8_t* in C++20
3941
auto R2 = LR"("Hello \ world")"; // const wchar_t*
4042
auto R3 = uR"("Hello \ world")"; // const char16_t*, encoded as UTF-16
4143
auto R4 = UR"("Hello \ world")"; // const char32_t*, encoded as UTF-32
4244

4345
// Combining string literals with standard s-suffix
4446
auto S0 = "hello"s; // std::string
45-
auto S1 = u8"hello"s; // std::string
47+
auto S1 = u8"hello"s; // std::string before C++20, std::u8string in C++20
4648
auto S2 = L"hello"s; // std::wstring
4749
auto S3 = u"hello"s; // std::u16string
4850
auto S4 = U"hello"s; // std::u32string
4951

5052
// Combining raw string literals with standard s-suffix
5153
auto S5 = R"("Hello \ world")"s; // std::string from a raw const char*
52-
auto S6 = u8R"("Hello \ world")"s; // std::string from a raw const char*, encoded as UTF-8
54+
auto S6 = u8R"("Hello \ world")"s; // std::string from a raw const char* before C++20, encoded as UTF-8,
55+
// std::u8string in C++20
5356
auto S7 = LR"("Hello \ world")"s; // std::wstring from a raw const wchar_t*
5457
auto S8 = uR"("Hello \ world")"s; // std::u16string from a raw const char16_t*, encoded as UTF-16
5558
auto S9 = UR"("Hello \ world")"s; // std::u32string from a raw const char32_t*, encoded as UTF-32
@@ -229,9 +232,15 @@ const char *escaped = "yes\\no";
229232

230233
A UTF-8 encoded string is a u8-prefixed, double-quote delimited, null-terminated array of type `const char[n]`, where *n* is the length of the encoded array in bytes. A u8-prefixed string literal may contain any graphic character except the double quotation mark (`"`), backslash (`\`), or newline character. A u8-prefixed string literal may also contain the escape sequences listed above, and any universal character name.
231234

235+
C++20 introduces the portable **`char8_t`** (UTF-8 encoded 8-bit Unicode) character type. In C++20, `u8` literal prefixes specify characters or strings of **`char8_t`** instead of **`char`**.
236+
232237
```cpp
238+
// Before C++20
233239
const char* str1 = u8"Hello World";
234240
const char* str2 = u8"\U0001F607 is O:-)";
241+
// C++20 and later
242+
const char8_t* u8str1 = u8"Hello World";
243+
const char8_t* u8str2 = u8"\U0001F607 is O:-)";
235244
```
236245

237246
### Wide string literals
@@ -259,8 +268,9 @@ A raw string literal is a null-terminated arrayβ€”of any character typeβ€”that c
259268
```cpp
260269
// represents the string: An unescaped \ character
261270
const char* raw_narrow = R"(An unescaped \ character)";
262-
const wchar_t* raw_wide = LR"(An unescaped \ character)";
263-
const char* raw_utf8 = u8R"(An unescaped \ character)";
271+
const wchar_t* raw_wide = LR"(An unescaped \ character)";
272+
const char* raw_utf8a = u8R"(An unescaped \ character)"; // Before C++20
273+
const char8_t* raw_utf8b = u8R"(An unescaped \ character)"; // C++20
264274
const char16_t* raw_utf16 = uR"(An unescaped \ character)";
265275
const char32_t* raw_utf32 = UR"(An unescaped \ character)";
266276
```
@@ -295,7 +305,8 @@ goodbye)";
295305
//#include <string>
296306
//using namespace std::string_literals;
297307
string str{ "hello"s };
298-
string str2{ u8"Hello World" };
308+
string str2{ u8"Hello World" }; // Before C++20
309+
u8string u8str2{ u8"Hello World" }; // C++20
299310
wstring str3{ L"hello"s };
300311
u16string str4{ u"hello"s };
301312
u32string str5{ U"hello"s };
@@ -380,18 +391,17 @@ The actual result is a hexadecimal 5F, which is the ASCII code for an underscore
380391
"\x05" "five" // Use string splicing.
381392
```
382393

383-
`std::string` literals, because they're `std::string` types, can be concatenated with the **`+`** operator that is defined for [`basic_string`](../standard-library/basic-string-class.md) types. They can also be concatenated in the same way as adjacent string literals. In both cases, the string encoding and the suffix must match:
394+
`std::string` literals (and the related `std::u8string`, `std::u16string`, and `ste::u32string`) can be concatenated with the **`+`** operator that's defined for [`basic_string`](../standard-library/basic-string-class.md) types. They can also be concatenated in the same way as adjacent string literals. In both cases, the string encoding and the suffix must match:
384395

385396
```cpp
386397
auto x1 = "hello" " " " world"; // OK
387398
auto x2 = U"hello" " " L"world"; // C2308: disagree on prefix
388-
auto x3 = u8"hello" " "s u8"world"s; // OK, agree on prefixes and suffixes
389-
auto x4 = u8"hello" " "s u8"world"z; // C3688, disagree on suffixes
399+
auto x3 = u8"hello" " "s u8"world"z; // C3688, disagree on suffixes
390400
```
391401

392402
### String literals with universal character names
393403

394-
Native (non-raw) string literals may use universal character names to represent any character, as long as the universal character name can be encoded as one or more characters in the string type. For example, a universal character name representing an extended character can't be encoded in a narrow string using the ANSI code page, but it can be encoded in narrow strings in some multi-byte code pages, or in UTF-8 strings, or in a wide string. In C++11, Unicode support is extended by the `char16_t*` and `char32_t*` string types:
404+
Native (non-raw) string literals may use universal character names to represent any character, as long as the universal character name can be encoded as one or more characters in the string type. For example, a universal character name representing an extended character can't be encoded in a narrow string using the ANSI code page, but it can be encoded in narrow strings in some multi-byte code pages, or in UTF-8 strings, or in a wide string. In C++11, Unicode support is extended by the `char16_t*` and `char32_t*` string types, and C++20 extends it to the `char8_t` type:
395405

396406
```cpp
397407
// ASCII smiling face
@@ -401,7 +411,8 @@ const char* s1 = ":-)";
401411
const wchar_t* s2 = L"πŸ˜‰ = \U0001F609 is ;-)";
402412

403413
// UTF-8 encoded SMILING FACE WITH HALO (U+1F607)
404-
const char* s3 = u8"πŸ˜‡ = \U0001F607 is O:-)";
414+
const char* s3a = u8"πŸ˜‡ = \U0001F607 is O:-)"; // Before C++20
415+
const char8_t* s3b = u8"πŸ˜‡ = \U0001F607 is O:-)"; // C++20
405416

406417
// UTF-16 encoded SMILING FACE WITH OPEN MOUTH (U+1F603)
407418
const char16_t* s4 = u"πŸ˜ƒ = \U0001F603 is :-D";
@@ -414,4 +425,4 @@ const char32_t* s5 = U"😎 = \U0001F60E is B-)";
414425

415426
[Character sets](../cpp/character-sets.md)\
416427
[Numeric, Boolean, and pointer literals](../cpp/numeric-boolean-and-pointer-literals-cpp.md)\
417-
[User-Defined Literals](../cpp/user-defined-literals-cpp.md)
428+
[User-defined literals](../cpp/user-defined-literals-cpp.md)

0 commit comments

Comments
Β (0)