'\ u0B95'是多字符文字吗?

时间:2012-11-25 01:12:16

标签: c++ character-encoding c++11 literals

a previous answer I gave中,我回复了以下警告,其原因是'\u0B95'需要三个字节,因此多字符文字

warning: multi-character character constant [-Wmultichar]

但实际上,我认为我不对,我认为gcc也不是。标准规定:

  

包含多个 c-char 的普通字符文字是多字符文字

c-char 的一个生产规则是通用字符名称(即\uXXXX\UXXXXXXXX)。由于\u0B95是单个 c-char ,因此这不是多字符文字。但现在它变得凌乱。该标准还说:

  

包含单个 c-char 的普通字符文字具有类型char,其值等于 c-char 在执行字符集中。

因此,我的文字具有类型char和执行字符集中的字符值(如果该集合中不存在,则为实现定义的值)。 char只被定义为足以存储基本字符集的任何成员(实际上不是由标准定义,但我认为它意味着基本的执行字符集):

  

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

因此,由于执行字符集是char可以容纳的所有值的超集,因此我的字符可能不适合char

那么 我的char有什么价值?这似乎没有在任何地方定义。该标准确实说明对于char16_t文字,如果该值不可表示,则该程序是不正确的。但它没有说普通文字。

那是怎么回事?这只是标准中的一个混乱还是我错过了什么?

4 个答案:

答案 0 :(得分:1)

我认为如下:

  

字符文字的值是实现定义的,如果它超出为char定义的实现定义的范围(对于没有pre fi x的文字)... (来自section 2.14.3.4)

如果'\u0B95'落在为char定义的实现定义范围之外(如果char是8位,那么它的值将被实现定义,此时GCC可以使其值成为多个c-char s的序列,从而成为多字符文字。

答案 1 :(得分:1)

有人发布了一个答案,正确回答了我问题的第二部分(char会有什么价值?)但后来删除了他们的帖子。由于那部分是正确的,我将在这里与我对第一部分的答案一起重现(这是一个多字符文字?)。


'\u0B95'不是多字符文字,而gcc在这里是错误的。如问题中所述,多字符文字由(§2.14.3/ 1)定义:

  

包含多个 c-char 的普通字符文字是多字符文字

由于通用字符名称 c-char 的一个扩展,因此文字'\u0B95'只包含一个 c-char < / em>的。如果普通文字不能包含\u0B95通用字符名称,则将其视为六个单独的字符(\u,{ {1}}等)但我无法在任何地方找到这个限制。因此,它是单个字符,文字不是多字符文字。

为了进一步支持这一点,为什么它被认为是多个字符?此时我们甚至没有给它编码,所以我们不知道它会占用多少字节。在UTF-16中,它需要2个字节,在UTF-8中需要3个字节,在某些想象编码中它只需要1个字节。

那么字符文字会有什么价值?首先,通用字符名称被映射到执行字符集中的相应编码,除非它没有映射,在这种情况下它具有实现定义的编码(§2.14.3/ 5): / p>

  

通用字符名称被转换为名称中的字符在相应执行字符集中的编码。如果没有这样的编码,则通用字符名称将转换为实现定义的编码。

无论哪种方式,0文字的值都等于编码的数值(§2.14.3/ 1):

  

包含单个 c-char 的普通字符文字具有类型char,其值等于执行字符集中c-char编码的数值。

现在是重要部分,不方便地隐藏在本节后面的另一段中。如果该值无法在char中表示,则会获得实现定义的值(§2.14.3/ 4):

  

如果字符文字的值超出为char定义的实现定义的范围(对于没有前缀的文字),则字符文字的值是实现定义的...

答案 2 :(得分:1)

你是对的,根据规范'\u0B95'是一个char类型的字符文字,其值等于执行字符集中字符的编码。你是对的,规则没有说明由于单个char无法表示该值而导致char文字无法实现的情况。行为未定义。

在此问题上向委员会提交了缺陷报告:例如,http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#912

目前提出的解决方案似乎是指定这些字符文字也是int并且具有实现定义的值(尽管提议的语言不太适合),就像multichar文字一样。我不是那种解决方案的粉丝,我认为更好的解决方案就是说这些文字是不正确的。

这是在clang中实现的:http://coliru.stacked-crooked.com/a/952ce7775dcf7472

答案 3 :(得分:0)

因为你没有字符编码前缀gcc(和任何其他符合标准的编译器)会看到'\u0B95'并认为1)char类型和2)多字符,因为字符串中有多个字符代码。

  • u'\u0B95'是UTF16角色。
  • u'\u0B95\u0B97'是多字符UTF16字符。
  • U'\ufacebeef'是UTF32字符。