字符集 - 不清楚

13

该标准定义了:

  • 基本源字符集

  • 基本执行字符集及其宽字符对应物

此外,它还定义了“执行字符集”及其宽字符对应物如下:

$2.2/3- “执行字符集和执行宽字符集是基本执行字符集和基本执行宽字符集的超集。执行字符集的成员值为实现定义,并且任何附加成员都是特定于语言环境的。”

问题1:我不认为我完全理解了这个内容,特别是最后一句话。对于这个方面有什么提示吗?

进一步地,

$3.9.1 - “声明为字符(char)的对象应足够大,以存储实现的基本字符集的任何成员。”

问题2:在3.9.1中,“基本字符集”一词是否意味着“基本执行字符集”?

1个回答

22

在IT技术中,你需要区分源字符集、执行字符集、传输执行字符集及其基本版本:

基本源字符集:

§2.1.1:基本源字符集由96个字符组成[...]

该字符集恰好包含96个字符,适合7位。例如@等字符不包括在内。

让我们举一些基本源字符的示例二进制表示。它们可以是完全任意的,没有必要与ASCII值对应。

A -> 0000000
B -> 0100100
C -> 0011101

基本执行字符集...

§2.1.3:基本执行字符集和基本执行宽字符集应分别包括基本源字符集的所有成员,加上表示警报、退格和回车的控制字符,加上一个空字符(分别是空宽字符),其表示具有所有零位。

如上所述,基本执行字符集包含所有基本源字符集的成员。它仍不包括任何其他字符,如@。基本执行字符集可以具有不同的二进制表示。

如上所述,基本执行字符集包含回车、空字符和其他字符的表示。

A          -> 10110101010
B          -> 00001000101    <- basic source character set
C          -> 10101011111
----------------------------------------------------------
null       -> 00000000000
Backspace  -> 11111100011

如果基本执行字符集长度为11位(就像这个例子),char数据类型应足够大以存储11位,但它可能会更长。

…和基本执行宽字符集:

基本执行宽字符用于宽字符(wchar_t)。它基本上与基本执行宽字符集相同,但也可以具有不同的二进制表示。

A          -> 1011010101010110101010
B          -> 0000100010110101011111    <- basic source character set
C          -> 1010100101101000011011
---------------------------------------------------------------------
null       -> 0000000000000000000000
Backspace  -> 1111110001100000000001

唯一固定的成员是空字符,它需要是一系列0位。

基本字符集之间的转换:

§2.1.1.5:字符字面值和字符串字面值中的每个源字符集成员、转义序列或通用字符名都会被转换为执行字符集(2.13.2、2.13.4)的成员。

然后,在编译C++源文件时,将源字符集的每个字符转换为基本执行(宽)字符集。

例如:

const char* string0   =  "BA\bC";
const wchar_t string1 = L"BA\bC";

因为string0是普通字符,所以它将被转换为基本执行字符集,而string1将被转换为基本执行宽字符集。

string0 -> 00001000101 10110101010 11111100011 10101011111
string1 -> 0000100010110101011111 1011010101010110101010    // continued
           1111110001100000000001 1010100101101000011011

有关文件编码的一些内容:

有几种文件编码。例如 ASCII,它是7位长的。Windows-1252,它是8位长的(也称为ANSI)。 ASCII 不包含非英语字符。ANSI 包含一些欧洲字符,如 ä Ö ä Õ ø

UTF-8UTF-32 这样的新文件编码可以包含任何语言的字符。 UTF-8 的字符长度可变。 UTF-32 是32位字符长。

文件编码要求:

大多数编译器都提供命令行开关来指定源文件的文件编码。

C++源文件需要使用具有基本源字符集表示的文件编码进行编码。例如:源文件的文件编码需要具有对 ; 字符的表示。

如果您可以在所选作为源文件编码的编码中键入字符 ;,则该编码不适合作为 C++ 源文件编码。

非基本字符集:

未包含在基本源字符集中的字符属于源字符集。源字符集等同于文件编码。

例如: @ 字符未包含在基本源字符集中,但它可以包含在源字符集中。输入源文件的所选文件编码可能包含 @ 的表示。如果没有表示 @, 则不能在字符串中使用字符 @

未包含在基本(宽)字符集中的字符属于执行(宽)字符集。

请记住,编译器将字符从源字符集转换为执行字符集和执行宽字符集。因此需要找到一种这些字符可以被转换的方式。

例如:如果您将 Windows-1252 指定为源字符集的编码,并将 ASCII 指定为执行宽字符集,则无法转换此字符串:

const char* string0 = "string with European characters ö, Ä, ô, Ð.";

这些字符无法用 ASCII 表示。

指定字符集:

以下是使用gcc指定字符集的一些示例。默认值已包含在内。

-finput-charset=UTF-8         <- source character set
-fexec-charset=UTF-8          <- execution character set
-fwide-exec-charset=UTF-32    <- execution wide character set

使用UTF-8和UTF-32作为默认编码方式,C++源文件可以包含任何语言的字符。UTF-8字符可以在两种方向上无问题地进行转换。

扩展字符集:

§1.1.3:多字节字符是一个由一个或多个字节组成的序列,表示源或执行环境的扩展字符集的成员。 扩展字符集是基本字符集(2.2)的超集。

多字节字符比普通字符的长度更长。它们包含一个转义序列,表示它们是多字节字符。

根据用户运行时环境中设置的地区设置处理多字节字符。这些多字节字符在运行时被转换为用户环境中的编码集。


2
这句话有点难理解:“如果您可以在被选为源文件编码的编码中键入字符;,则该编码不适用于C++源文件编码。”它是什么意思? - JCx
我认为-fexec-charset=UTF-8是一个不好的例子,因为它不符合规范。这个想法很清楚:基本执行字符集应该是Unicode,但是(正如你自己强调的那样)char应该是20位宽度以容纳所有Unicode值。然而,UTF-8是一种可变长度编码,这意味着它只适用于扩展字符集。 - MSalters
1
@joke 笑话:打错字了:“如果你不能输入分号字符;”。 - C.M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接