C++ C11编译。翻译阶段#1和#5。通用字符名

C++ C11编译。翻译阶段#1和#5。通用字符名,c++,c,c++11,unicode,c11,C++,C,C++11,Unicode,C11,我试图理解C11标准中的通用字符名,发现C11标准的N1570草案在翻译阶段1和5以及其中UCS的形成和处理方面比C++11标准的细节要少得多。这是每个人都要说的: 翻译阶段1 N1570草案C11 5.1.1.2p1.1: 物理源文件多字节字符以实现定义的方式映射到源字符集(如有必要,为行尾指示符引入新行字符)。三角图序列被相应的单字符内部表示替换 C++11 2.2p1.1: 如有必要,将以实现定义的方式将物理源文件字符映射到基本源字符集(为行尾指示符引入新行字符)。接受的物理源文件字符集由

我试图理解C11标准中的通用字符名,发现C11标准的N1570草案在翻译阶段1和5以及其中UCS的形成和处理方面比C++11标准的细节要少得多。这是每个人都要说的:

翻译阶段1 N1570草案C11 5.1.1.2p1.1:

物理源文件多字节字符以实现定义的方式映射到源字符集(如有必要,为行尾指示符引入新行字符)。三角图序列被相应的单字符内部表示替换

C++11 2.2p1.1:

如有必要,将以实现定义的方式将物理源文件字符映射到基本源字符集(为行尾指示符引入新行字符)。接受的物理源文件字符集由实现定义。Trigraph序列(2.4)由相应的单字符内部表示替换。不在基本源字符集(2.3)中的任何源文件字符将替换为指定该字符的通用字符名。(一个实现可以使用任何内部编码,只要源文件中遇到的实际扩展字符和源文件中表示为通用字符名的相同扩展字符(即使用\uxxx表示法)被等效处理,除非此替换以原始字符串文字还原。)

翻译阶段5 N1570草案C11 5.1.1.2p1.5:

将字符常量和字符串文本中的每个源字符集成员和转义序列转换为执行字符集的相应成员;[……]

C++2.2p1.5:

字符文字或字符串文字中的每个源字符集成员,以及字符文字或非原始字符串文字中的每个转义序列和通用字符名,都转换为执行字符集的相应成员;[……]

(强调差异)

问题
  • 在C++11标准中,很明显,不在基本源字符集中的源文件字符被转换为UCS,并且它们被完全视为同一位置的UCN,只有原始字符串例外。C11也是这样吗?当C11编译器看到一个多字节UTF-8字符,如
    °
    ,它是否也会在第1阶段将其转换为
    \u00b0
    ,并将其视为
    \u00b0
    出现在那里

  • 换言之,在哪一个翻译阶段(如果有的话)结束时,以下代码片段在C11中第一次转换为文本等价形式

    const char*hell°=“hell°”;
    

    const char*hell\u00b0=“hell\u00b0”;
    
  • 如果在2.中,答案是“无”,那么在哪个翻译阶段,这两个标识符第一次被理解为指同一事物,尽管文本不同

  • 在C11中,字符/字符串文本中的UCS是否也在第5阶段转换?如果是这样,为什么在标准草案中省略这一点
  • C11和C++11中如何处理标识符中的UCS(与前面提到的字符/字符串文本相反)?它们是否也在第5阶段转换?或者这是实现定义的东西?例如,GCC是否以UCN编码的形式或实际的UTF-8打印出此类标识符
  • 评论变成了答案

    有趣的问题

    C标准可以保留更多未声明的转换,因为它们是实现定义的(并且C没有原始字符串来混淆问题)

  • 它在C标准中所说的就足够了——只是它让你的问题1无法回答
  • 我认为,Q2必须是“第5阶段”,需要注意的是“令牌流是等效的”
  • Q3严格来说是不适用的,但第7阶段可能是答案
  • Q4是“是”,之所以这么说是因为它提到了“逃逸序列”,而UCS是逃逸序列
  • Q5也是“第五阶段”
  • 在第1阶段和第5阶段中,C++11强制执行的过程是否可以被视为符合C11的措辞(将原始字符串放在一边)


    我认为它们实际上是一样的;差异主要来自于C++特有的原始文字问题。一般来说,C和C++标准尽量不使事物有不同的差别,特别是尝试预处理器和低级字符的分析(两者都是相同的)(自从C99增加了对C++<代码> //<代码>注释的支持以来,这一点就变得更容易了,但是显然,在C++ C++ 11中添加原始文本变得更加困难)。


    总有一天,我将不得不更彻底地研究原始文字符号及其含义。

    首先,请注意,这些区别自1998年以来就存在;UCN首先在新标准C++98(ISO/IEC 14882,第一版:1998)中引入,然后进入C标准的C99修订版;但是C委员会(以及现有的实现者及其预先存在的实现)并不认为C++方式是实现这个窍门的唯一方式,特别是使用角点情况和使用比Unicode更小的字符集,或者只是不同的方式;例如,在1998年,要求将映射表从任何支持的编码发送到Unicode是C供应商的当务之急

  • C标准(有意识地)避免决定这一点,并让编译器选择如何继续。虽然您的推理显然是在源代码和执行所使用的UTF-8字符集的上下文中进行的,但是有大量(并且预先存在)不同的C99/C11编译器可用,它们使用不同的集合;A.
    #define str(t) #t
    #define str_is(x, y)  const char * x = y " is " str(y)
    str_is(hell°,      "hell°");
    str_is(hell\u00B0, "hell\u00B0");
    
    const char* hell°      = "hell°"       " is " "\"hell\\u00b0\"";
    const char* hell\u00b0 = "hell\\u00b0" " is " "\"hell\\u00b0\"";