在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
文字,如果该值不可表示,则该程序是不正确的。但它没有说普通文字。
那是怎么回事?这只是标准中的一个混乱还是我错过了什么?
答案 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字符。等