【问题标题】:What are the different character sets used for?不同的字符集用于什么?
【发布时间】:2015-01-10 03:15:30
【问题描述】:

C++ 标准提到了多种不同的字符集。特别是,它提到了以下字符集:

  1. 在 2.2 [lex.phases] 项目符号 1 中提到了物理源文件字符及其到基本源字符集的映射。
  2. 在 2.2 [lex.phases] 项目符号 2 中提到了 执行字符集
  3. 在 2.3 [lex.charset] 第 3 段中提到了基本执行字符集基本执行宽字符集。
  4. 相同的第 2.3 节 [lex.charset] 3 还提到了一个执行字符集和一个执行宽字符集
  5. 在读取或写入文件时,这些文件使用其他字符集。

所有这些不同的字符集用于什么,它们之间的转换是如何完成的,以及这些值中的哪些是区域设置相关的?尤其是字符串字面量是如何表示的?

【问题讨论】:

标签: c++ encoding utf-8


【解决方案1】:

以下是编译器本身使用的不同字符集的细分(实际上所有对标准的引用都是针对C++14):

  1. 物理源文件字符是在 C++ 源代码中使用的字符。很可能这些现在使用一些 Unicode 编码进行编码,例如 UTF-8UTF-16。如果您来自欧洲或美国背景,您可能正在使用ASCII,其字符方便地以相同的 UTF-8 编码(每个 ASCII 文件都是 UTF-8 文件,但不是相反)。物理源文件characters_也可能是不寻常的东西,例如EBCDIC
  2. 基本源字符集是编译器至少在概念上使用的。它是从物理源文件字符生成的,并将它们映射到它们各自的基本字符或使用通用字符名称表示物理源字符的基本字符序列(参见 2.2 [lex.phases]第 1 段)。基本源字符集只是一组 96 个字符(2.3 [lex.charset] 第 1 段):

    a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 _ { } [ ] # ( ) % : ; . ? * + - / ^ & | ~ ! = , \" '

    以及 5 个特殊字符空格 (' ')、水平制表符 (\t)、垂直制表符 (\v)、换页 (\f) 和换行符 (\n)

    物理源字符集和基本字符集之间的映射是实现定义的。

  3. 基本执行字符集基本执行宽字符集是能够表示由一些特殊字符扩展的基本源字符集的字符集: p>

    alert ('\a')、退格 ('\b')、回车 ('\r') 和空字符 ('\0')

    非宽版和宽版的区别在于字符是用char还是wchar_t表示。

  4. 执行字符集执行宽字符集是基本字符集和基本宽字符集的实现定义扩展。在 2.3 [lex.charset] 第 3 段中指出,执行字符集的附加成员和附加成员的值是特定于语言环境的。目前尚不清楚指的是哪个语言环境,但我怀疑编译期间使用的语言环境是指的。在任何情况下,执行字符集都是由实现定义的(也根据 2.3 [lex.charset] 第 3 段)。

  5. 字符和字符串文字最初使用基本源字符集表示,其中一些字符可能使用通用字符名称。所有这些都在编译时转换为执行字符集。根据 2.14.3 [lex.ccon] 在执行字符集中可表示为一个 char 的字符文字才有效。如果需要多个chars,则可以有条件地支持字符文字(并且它们的类型为int)。对于字符串文字,转换在 2.14.5 [lex.string] 中描述。第 9 段指出 UTF-8 字符串文字(例如 u8"hello")会产生一系列与 UTF-8 字符串的代码单元相对应的值。否则,字符和通用字符名称的翻译与字符文字的翻译相同(特别是,它是实现定义的),尽管字符导致窄字符串的多字节序列只会导致多个字符(这种情况下不需要支持对于字符文字)。

到目前为止,只考虑编译的结果。任何不属于字符或字符串文字的字符都用于指定代码的作用。有趣的问题是文字发生了什么?文字基本上都被翻译成实现定义的表示。这是实现定义的意思是它在某个地方记录了应该发生的事情,但它可能在不同的实现之间有所不同。

在处理来自某个地方的字符或字符串时,这有什么帮助?好吧,任何读取的字符或字符串都会转换为相应的执行字符集。特别是,当读取文件时,所有字符都转换为这种通用表示。当然,要使这种转换起作用,需要根据该文件的编码设置用于读取文件的语言环境。如果未明确提及区域设置,则使用最初由系统确定的全局区域设置。初始全局语言环境可能是基于用户偏好以某种方式设置的,例如,不基于环境变量。如果读取的文件使用与此全局语言环境不同的编码,则需要使用与文件编码匹配的相应不同语言环境。

相应地,当使用其中一种执行字符集写入字符时,这些字符会根据当前语言环境指定的编码进行转换。同样,如果需要特定的编码,可能需要替换语言环境。

所有这些实际上意味着在程序内部,所有字符串和字符处理都使用实现定义的执行字符集进行。程序读取的所有字符都需要转换为此字符集,并且写入的所有字符都以该执行字符集中的字符开头,并且需要适当地转换为外部编码。当然,如果在理想设置中,执行字符集和外部表示之间的转换是身份,例如,因为执行字符集使用 UTF-8,而外部表示也使用 UTF-8。相应地,对于执行宽字符集,除了在这种情况下,将使用 UTF-16(UTF-16 的两种变体之一可以使用big endian or little endian 表示)。

【讨论】:

  • 小更正:在要点 2 下,您列出了基本的源字符集。最后一个字符 newline 归因于错误的转义序列(\t\n)。
猜你喜欢
  • 2012-09-11
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多