什么保证存储在 char32_t 或 char16_t 到 char 中的 UTF-8 代码单元的 static_cast 会按预期结果?
What guarantees that a static_cast of a UTF-8 code unit stored in a char32_t or char16_t to char will turn out as expected?
使用 C++11 标准时,是否可以保证存储在 char32_t
或 char16_t
代码点中的 ASCII 字符将正确转换为 char
?
char32_t
和 char16_t
都定义为始终无符号 (http://en.cppreference.com/w/cpp/language/types)。但是,char
可能有符号或无符号,具体取决于系统。
我假设 ASCII 字符始终有效:
char32_t original = U'b';
char value = static_cast<char>(original);
但是,UTF-8
代码单元的值以第一位 == 1 开头,并在转换期间使用位掩码从 UTF-32
字符中提取,例如:
char32_t someUtf32CodeUnit = 0x00001EA9;
// Third code-unit of ẩ
char extractedCodeUnit = static_cast<char>(((someUtf32CodeUnit >> 6) & 0x3F) | 0x80);
是否保证所有系统上的转换都将以相同的方式工作(导致所述 UTF-8
代码单元的相同预期位)或者未签名<->签名转换可能会有所不同?
编辑:
据我所知,C++(包括 C++11)对于用于 char
类型的编码是不可知的。唯一的要求 (§3.9.1.1) 是 char
必须能够存储 §2.3 中定义的基本字符集的任何字符。因此,即使是集合外的 ASCII 字符,如 @
或 `
,也不能保证存储在 char
中。它们的代码点值显然可以存储,但机器可能会将它们解释为不同的字形(对于 isalpha
和类似的函数)
即使您只是对存储值感兴趣,在您的示例中您尝试 static_cast
一个 int
表达式到 char
。如果您的 char
是有符号类型且值大于 127,则结果由实现定义,详情请参阅 this answer。
使用 C++11 标准时,是否可以保证存储在 char32_t
或 char16_t
代码点中的 ASCII 字符将正确转换为 char
?
char32_t
和 char16_t
都定义为始终无符号 (http://en.cppreference.com/w/cpp/language/types)。但是,char
可能有符号或无符号,具体取决于系统。
我假设 ASCII 字符始终有效:
char32_t original = U'b';
char value = static_cast<char>(original);
但是,UTF-8
代码单元的值以第一位 == 1 开头,并在转换期间使用位掩码从 UTF-32
字符中提取,例如:
char32_t someUtf32CodeUnit = 0x00001EA9;
// Third code-unit of ẩ
char extractedCodeUnit = static_cast<char>(((someUtf32CodeUnit >> 6) & 0x3F) | 0x80);
是否保证所有系统上的转换都将以相同的方式工作(导致所述 UTF-8
代码单元的相同预期位)或者未签名<->签名转换可能会有所不同?
编辑:
据我所知,C++(包括 C++11)对于用于 char
类型的编码是不可知的。唯一的要求 (§3.9.1.1) 是 char
必须能够存储 §2.3 中定义的基本字符集的任何字符。因此,即使是集合外的 ASCII 字符,如 @
或 `
,也不能保证存储在 char
中。它们的代码点值显然可以存储,但机器可能会将它们解释为不同的字形(对于 isalpha
和类似的函数)
即使您只是对存储值感兴趣,在您的示例中您尝试 static_cast
一个 int
表达式到 char
。如果您的 char
是有符号类型且值大于 127,则结果由实现定义,详情请参阅 this answer。