10

我之前给出的答案中,我回应了以下警告,原因是'\u0B95'需要三个字节,多字符文字也是如此:

warning: multi-character character constant [-Wmultichar]

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

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

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

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

所以我char的文字在执行字符集中具有字符的类型和值(或者如果它在该集中不存在,则为实现定义的值)。char仅定义为足够大以存储基本字符集的任何成员(标准实际上并未定义,但我认为它表示基本执行字符集):

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

因此,由于执行字符集是 achar可以保存的所有值的超集,我的角色可能不适合char.

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

发生什么了?这只是标准中的一团糟还是我错过了什么?

4

4 回答 4

1

有人发布的答案正确回答了我的问题的第二部分(有什么价值char?),但后来删除了他们的帖子。由于那部分是正确的,我将在此处与第一部分的答案一起复制它(它是多字符文字吗?)。


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

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

由于通用字符名称是c-char的一种扩展,因此文字'\u0B95'仅包含一个c-char。如果普通文字不能包含通用字符名称\u0B95被视为六个单独的字符(\, u,0等),那将是有意义的,但我在任何地方都找不到这个限制。因此,它是单个字符,而文字不是多字符文字。

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

那么字符文字有什么价值呢?首先,universal-character-name映射到执行字符集中的相应编码,除非它没有映射,在这种情况下它具有实现定义的编码(第 2.14.3/5 节):

通用字符名称被转换为命名字符在适当执行字符集中的编码。如果没有这样的编码,universal-character-name 将被转换为实现定义的编码。

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

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

现在重要的部分,不方便地隐藏在本节进一步的不同段落中。如果该值不能在 中表示char,它将获得一个实现定义的值(第 2.14.3/4 节):

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

于 2012-11-25T19:42:09.803 回答
1

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

有关于这个问题向委员会提交的缺陷报告:例如,http ://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#912

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

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

于 2014-07-24T22:33:17.313 回答
1

我会争辩如下:

char如果字符文字的值超出了为(对于没有前缀的文字)定义的实现定义的范围...... (来自第 2.14.3.4 节)

如果'\u0B95'超出定义的实现定义范围char(如果char是 8 位),则它的值将由实现定义,此时 GCC 可以使其值成为多个c-chars 的序列,从而成为多字符文字。

于 2012-11-25T05:16:04.347 回答
0

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

  • u'\u0B95' 是一个 UTF16 字符。
  • u'\u0B95\u0B97'是一个多字符 UTF16 字符。
  • U'\ufacebeef' 是一个 UTF32 字符。

等等

于 2014-07-24T21:45:51.347 回答