4

我无法理解它在 c++ 标准中的含义:

任何不在基本源字符集 (2.3) 中的源文件字符都将替换为指定该字符的通用字符名。(实现可以使用任何内部编码,只要在源文件中遇到的实际扩展字符,以及在源文件中表示为通用字符名称的相同扩展字符(即,使用 \uXXXX 表示法)是等效处理,除非此替换在原始字符串文字中恢复。)

据我了解,如果编译器看到字符不在基本字符集中,它只是用这种格式的字符序列替换它'\uNNNN''\UNNNNNNN'。但我不知道如何获得这个 NNNN 或 NNNNNNNN。所以这是我的问题:如何进行转换

4

3 回答 3

3

请注意前面的句子,其中指出:

如有必要,物理源文件字符以实现定义的方式映射到基本源字符集(为行尾指示符引入换行符)。

也就是说,编译器如何实际解释构成文件的字符或字节完全取决于编译器。在进行这种解释时,它必须决定哪些物理字符属于基本源字符集,哪些不属于。如果一个角色不属于,则将其替换为通用角色名称(或者至少,效果就像它已经完成一样)。

这样做的目的是将源文件减少到一个非常小的字符集——基本源字符集中只有 96 个字符。任何不在基本源字符集中的字符都已替换为\uU以及一些十六进制数字 ( 0- F)。

通用字符名称是以下之一:

\uNNNN
\UNNNNNNNN

其中每个N都是十六进制数字。这些数字的含义在 §2.3 中给出:

由universal-character-name 指定的字符\UNNNNNNNN是ISO/IEC 10646 中字符短名称为的字符NNNNNNNN;Universal-character-name 指定的字符\uNNNN是 ISO/IEC 10646 中字符短名称为 的字符0000NNNN。如果通用字符名称的十六进制值对应于代理代码点(在0xD800-<code>0xDFFF 范围内,包括在内),则程序格式错误。

ISO/IEC 10646 标准起源于 Unicode 之前并定义了通用字符集 (UCS)。它将代码点分配给字符并指定这些代码点应如何编码。Unicode 联盟和 ISO 小组随后联手致力于 Unicode。Unicode 标准比 ISO/IEC 10646 规定的要多得多(算法、功能字符规范等),但现在这两个标准保持同步。

因此,您可以将NNNNorNNNNNNNN视为该字符的 Unicode 代码点。

例如,考虑源文件中包含以下内容的一行:

const char* str = "Hellô";

由于 ô 不在基本源字符集中,因此该行在内部被翻译为:

const char* str = "Hell\u00F4";

这将给出相同的结果。

您的代码中只有某些部分允许使用通用字符名称:

于 2013-03-09T14:42:17.590 回答
2

但我不知道如何获得这个 NNNN 或 NNNNNNNN。所以这是我的问题:如何进行转换?

映射是实现定义的(例如,§2.3 脚注 14)。例如,如果我将以下文件另存为 Latin-1:

#include <iostream>

int main() {
    std::cout << "Hallö\n";
}

g++在 OS X 上编译它,运行后我得到以下输出:

Hell�

…但如果我将它保存为 UTF-8,我会得到这个:

Hellö

因为 GCC 假定 UTF-8 作为我系统上的输入编码。

其他编译器可能会执行不同的映射。

于 2013-03-09T15:10:47.323 回答
1

因此,如果您的文件被调用Hello°¶.c,编译器将在内部使用该名称时,例如,如果我们这样做:

cout << __FILE__ << endl;

编译器将转换Hello°¶.cHello\u00b0\u00b6.c.

但是,当我尝试使用它时,g++它并没有这样做......

但汇编器输出包含:

.string "Hello\302\260\302\266.c"
于 2013-03-09T14:17:52.607 回答