在 @ Zaibis 的建议下(并与我自己的答案到What are the valid characters for macro names?以及? (and other unicode characters) in identifiers not allowed by g++有关)...
clang 允许很多“疯狂”的角色..虽然我一直在努力寻找很多押韵或原因-为什么有些是允许的(
例如,下面所有编译 A-OK (clang-700.1.76
)
#define ? ?: // OK (Pile of )
#define ■ @end // OK (HALFWIDTH BLACK SQUARE)
#define ? @intece // OK (NEGATIVE SQUARED LATIN CAPITAL LETTER K)
#define P @protocol // OK (FULLWIDTH LATIN CAPITAL LETTER P)
然而,以下所有结果在相同的编译器错误...
Macro name must be an identifier.
#define ☎ TEL
#define ❌ NO
#define ⇧ UP
#define 〓 ==
#define ? APPLE
clang
's docs refer to the issue,仅声明...
...支持 C99 和 C++ 中的扩展标识符。此功能允许标识符包含活动语言标准指定的某些 Unicode 字符;这些字符可以使用 UTF-8 编码直接写入源文件,也可以使用通用字符名称 (\ u00E0,\ U000000E0) 引用。
所以,我想我在问..什么是“主动语言标准”,以及如何找到合法标识符的权威来源。
我创建了following code只是为了看看clang
会如何处理它。在测试的大约 63488 个可能的标识符中,有 23 个发出警告,9506 个生成错误。这使得标识符中使用了将近 54,000 个有效字符。当然可以,但是谁被削减了?为什么?
正如其他人所提到的,ISO/IEC 9899:2011的附件 D 列出了 C11 中对通用字符名称有效的字符的十六进制值。(我不会在这里重复它。)我一直在寻找一个答案“为什么”选择这个列表。
字符集标准
首先,有两个相关的标准定义了一组字符:ISO/IEC 10646(定义UCS)和Unicode。为了进一步混淆(或简化)事物,它们都定义了相同的字符,因为 ISO 和 Unicode 将它们保留为synchronized。UCS 本质上只是一个字符映射,将值与一组字符相关联(“
C 中的通用字符名
通用字符名称 (UCN) 是 C99 (ISO / IEC 9899:1999) 中新添加的一项功能。在“国际标准的基本原理---编程语言---C”(Rev. 2, Oct. 1999) 中,目的是“允许在标识符、字符串文字和字符常量中使用任何 'native' 字符,同时保留
Rationale
I was ping that the same"rationale" doent from 1999would give a reason of why each extended character range was selected as acceptable for C99 ’ s UCN.The entire of the rationary ’ s Annex I is:
附件一标识符的通用字符名称(规范)
C9X 的一项新功能。
这不是什么道理。他们甚至不知道 C 标准将在哪xx年发布,所以它只是被称为“C9X”。后来的rationale doent from 2003稍微更有启发性:
附件 D 标识符的通用字符名称(规范)
C99 的新功能。
目的是保持与 ISO / IEC TR 10176 电流。
ISO/IEC TR 10176是“编写编程语言标准的指南”。它基本上是编写编程语言标准的人的指南。它包括在编程语言中使用字符集的指南以及“推荐的用户定义标识符扩展库”(附件 A)。但是,2003 年基本原理文档中的这句话只是“保持最新状态的意图”,而不是严格遵守 TR 10176 的承诺。
有一个公开可用的ISO/IEC TR 10176:2003 table字符。字符值参考 ISO 10646。该表将来自多种语言的字符范围分类为“大写”Lu
;“小写”Ll
;“数字,十进制数字”Nd
,“标点符号,连接符”Pc
;等。应该清楚使用什么分类
一个重要的提醒是,TR 10176 是技术报告,而不是标准。我在论坛上以及与其他编程语言(例如 Ada,COBOL 和 D 语言)相关的文档中发现了一些对它的引用。大部分讨论是关于这些语言的标准应遵循 TR 10176(不是标准)的紧密程度,并抱怨 TR 10176 落后于 ISO 10646 的更新。
也许最有启发性的是文档WG21/N3146:“针对 C 和 C 的扩展标识符字符的建议”。它始于 2010 年对标准机构的评论,建议对标识符的初始字符进行限制。它提到了有关 C 引用 TR 10176 的类似投诉,并根据Unicode's Identifier and Pattern Syntax和XML's Common Syntactic Constructs的限制,提出了哪些字符应被允许作为标识符的初始字符。
C11 中允许和不允许的字符
以下是扩展标识符字符的范围的编译列表。粗体范围是 C11 (ISO/IEC 9899:2011 Annex D) 中给出的范围。添加了一些关于 C11中未列出的斜体范围的注释 (即不允许)。它们在WG21/N3146中被标记为
00A8,00AA,00AD,00AF,00B2-00B5,00C0-00D6,00D8-00F6,00F8-00FF:(各种字符,如女性和男性序数指示符,带有变音符号的元音,数字字符,如上标数字,分数等)
(以前的差距):UAX31和 / 或XML均不允许。(通常是标点符号类型的标记,例如“”,货币符号 ¥£,数算符 × ÷ 等)
0100-167F:(拉丁文、希腊文、西里尔文、伯文、泰文、埃塞俄比亚文等 — — 其他很多)
1680:“Ogham 块包含特定于脚本的空间:”
1681-180D:(奥格姆、他加禄语、蒙古语等)
180E:“蒙古文块包含特定于脚本的空间”
180F-1FFF:(更多语言...语音,扩展拉丁语和希腊语等)
2000:启动“常规标点符号”块,但有些是允许的:
200B − 200D 、 202A − 202E 、 203F − 2040 、 2054 、 2060 − 206F:(从“通用标点符号”块中选择)
2070 − 218F:“上标和下标,货币符号,符号的组合变音符号,字母符号,数字形式”
2190-245F:“箭头,数算符,杂项技术,控制图片,光学字符识别”
2460-24FF:“封闭的字母数字”
2500:开始“框画、图块元素、几何形状”等。
2776-2793:(一些哑巴和带圆圈的哑巴)
2794-2BFF:(不同的 dingbat 集,数学符号,箭头,盲文图案等)
2C00-2DFF,2E80-2FFF:“Glagolitic,Latin Extended-C,Coptic,Georgian Supplement,Tifinagh,Ethiopic Extended,Cyrillic Extended-A”(CJK radical supplement)
3000:(“CJK 符号和标点符号”的开头,允许进行一些选择)
3004-3007 、 3021-302F 、 3031-303F:(允许“CJK 符号和标点”)
3040-D7FF:“平假名,片假名”,更多 CJK 表意文字,部首等。
D800-F8FF:(这将启动High和低代理区域(编码所需的数字空间)和Private Use)
FD 范围:F900-FD3D,FD40-FDCF,FDF0-FE44,FE47-FFFD:从“CJK 兼容性表意”,“伯语表示形式”等中选择10000-1FFFD,20000-2FFFD,30000-3FFFD,40000-4FFFD,50000-5FFFD,60000-6FFBFFFD,70000-
补充专用区域从 F0000 扩展到 10FFFF;[AltId]和[XML2008]都不允许该范围内的字符。
此外,对于P的任何值,[AltId]不允许每个平面的最后两个代码位置作为非字符,即PFFFE 或PFFFF 形式的每个位置。
C11附录 D.2 中的“最初不允许的字符范围”为0300 − 036F 、 1DC0 − 1DFF 、 20D0 − 20FF 、 FE20 − FE2F。
通过将WG21/N3146放在C11 standard的附录 D 旁边,可以推断出它们的排列方式。例如,似乎不允许使用数算符和标点符号。我希望这能阐明选择允许的字符的“原因”或“方式”。
TLDR;版本
合法标识符字符的权威来源是 C11 标准ISO/IEC 9899:2011(见附录 D)。
此列表基于技术报告ISO/IEC TR 10176,但带有modifications。
C2011 标准的第 6.4.2 节介绍了标识符的语法,其中包括宏名称,并根据附录 D.1 进行了解释。这些规定认为,每个标识符都可以包含下划线,大写和小写拉丁字母,十进制数字,组成“通用字符名称”的字符序列(受限制),以及实现定义的任何其他字符。
通用字符名称(UCN)是 Unicode 转义序列,类似于 Java,Pytn 和其他一些语言提供的 UCN:它们也以反斜杠(\
)开头,后跟u
或U
,以及四个或八个十六进制数字。在特定的十六进制数字序列上可能会出现一些限制,但是。
因此,从语法上讲并将讨论限制在标识符中标准要求允许的字符,下划线,(无重音)拉丁字母,十进制数字和反斜杠是 C 要求的唯一字符必须在标识符中得到支持。仅在 UCN 的上下文中需要支持反斜杠,并且在标识符中不允许所有有效的 UCN。此外,该标准不需要支持数字作为标识符的第一个字符。
另一方面,该标准非常宽松,允许在标识符中使用“其他实现定义的字符”,包括第一个字符。原则上,根据实现的决定,即使是十进制数字,否则不能作为标识符中的第一个字符,也可以在该规定的位置允许。如果您希望您的代码在实现之间可移植,那么您将避免在任何地方依赖此规定。如果您想知道特定实现允许哪些字符,则必须参考其文档。
您自己链接到并引用了 Clang 的文档中相同的实现定义的细节,这将更加自由--它允许所有的字符通过 UTF 序列表示为标识符,如果它们是一个字节,那么在这种情况下也可以表示。
如前所述,C11 Standard定义了几个允许的 Unicode 字符范围。
00A8,00AA,00AD,00AF,00B2 − 00B5,00B7 − 00BA,00BC − 00BE,00C0 − 00D6,00D8 − 00F6,00F8 − 00FF
0100 − 167F 、 1681 − 180D 、 180F − 1FFF
200B − 200D 、 202A − 202E 、 203F − 2040 、 2054 、 2060 − 206F
2070 − 218F 、 2460 − 24FF 、 2776 − 2793 、 2C00 − 2DFF 、 2E80 − 2FFF
3004 − 3007,3021 − 302F,3031 − 303F
3040 − D7FF
F900 − FD3D 、 FD40 − FDCF 、 FDF0 − FE44 、 FE47 − FFFD
10000 − 1FFFD 、 20000 − 2FFFD 、 30000 − 3FFFD 、 40000 − 4FFFD 、 50000 − 5FFFD 、 60000 − 6FFFD 、 70000 − 7FFFD 、 80000 − 8FFFD 、 90000 − 9FFFD 、 A0000 − AFFFD 、 B0000 − BFFFD 、 C0000 − CFFFD 、 D0000 − DFFFD 、 E0000 − EFFFD
这也意味着从使用中排除了多个字符范围。
从您的示例中:
它是260E
,并且来自“杂项符号”块:2600-26FF
,这意味着您错过了all of these
274C
,来自“Dingbats”块:2700-27BF
是all of these,但其中一些是允许的(2776−2793
)
是21E7
,并且来自“箭头”块:2190-21FF
,这意味着您错过了all of these
是3013
,来自“CJK 符号和标点”块:3000-303F
是all these,但其中一些是允许的。
1F34E
,来自“杂项符号和象形文字”块:1F300-1F5FF
是all these,实际上应该可以工作
(也许是clang
问题?顺便说一句,这不是在我的家用电脑(Ubuntu)上显示,而是在我的工作电脑(Win7)上显示)
本站系公益性非盈利分享网址,本文来自用户投稿,不代表边看边学立场,如若转载,请注明出处
评论列表(7条)