什么构成了 "valid" C 标识符?
What constitutes a "valid" C Identifier?
根据@Zaibis 的建议(并且与我自己的 answer to What are the valid characters for macro names?, as well as (and other unicode characters) in identifiers not allowed by g++ 相关))...
clang allows a lot of "crazy" characters.. although I have struggled to find much rhyme or reason - as to why some are allowed ( ϟ ツ ⌘ ☁ ½), and others are not (▶︎ ∀ ★ ©).
比如下面都编译A-OK(clang-700.1.76
)
#define ?: // OK (Pile of poo)
#define ■ @end // OK (HALFWIDTH BLACK SQUARE)
#define @interface // 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,仅说明...
... support for extended identifiers in C99 and C++. This feature allows identifiers to contain certain Unicode characters, as specified by the active language standard; these characters can be written directly in the source file using the UTF-8 encoding, or referred to using universal character names (\u00E0, \U000000E0).
所以,我想我是在问.. "active language standard" 是什么,我怎样才能找到合法标识符的权威来源。
我创建 following code 只是为了看看 clang
会用它做什么。在测试的大约 63488 个可能的标识符中,有 23 个发出了警告,9506 个产生了错误。剩下将近 54,000 个有效字符可用于标识符。当然够了,但谁被裁掉了?为什么?
6.4.2 Identifiers
6.4.2.1 General
...
3 Each universal character name in an identifier shall designate a character whose encoding
in ISO/IEC 10646 falls into one of the ranges specified in D.1.71) The initial character
shall not be a universal character name designating a character whose encoding falls into
one of the ranges specified in D.2. An implementation may allow multibyte characters
that are not part of the basic source character set to appear in identifiers; which characters
and their correspondence to universal character names is implementation-defined.
...
71) On systems in which linkers cannot accept extended characters, an encoding of the universal character
name may be used in forming valid external identifiers. For example, some otherwise unused
character or sequence of characters may be used to encode the \u in a universal character name.
Extended characters may produce a long external identifier.
...
Annex D
(normative)
Universal character names for identifiers
1 This clause lists the hexadecimal code values that are valid in universal character names
in identifiers.
D.1 Ranges of characters allowed
1 00A8, 00AA, 00AD, 00AF, 00B2−00B5, 00B7−00BA, 00BC−00BE, 00C0−00D6,
00D8−00F6, 00F8−00FF
2 0100−167F, 1681−180D, 180F−1FFF
3 200B−200D, 202A−202E, 203F−2040, 2054, 2060−206F
4 2070−218F, 2460−24FF, 2776−2793, 2C00−2DFF, 2E80−2FFF
5 3004−3007, 3021−302F, 3031−303F
6 3040−D7FF
7 F900−FD3D, FD40−FDCF, FDF0−FE44, FE47−FFFD
8 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
D.2 Ranges of characters disallowed initially
1 0300−036F, 1DC0−1DFF, 20D0−20FF, FE20−FE2F
根据附录 D.1 解释的 C2011 标准第 6.4.2 节介绍了包括宏名称在内的标识符语法。这些规定规定每个标识符都可以包含下划线、大写和小写拉丁字母、十进制数字、构成 "universal character names"(受限制)、 的字符序列以及实现定义的任何其他字符.
通用字符名称 (UCN) 是 Unicode 转义序列,类似于 Java、Python 和其他一些语言提供的转义序列:它们以反斜杠 (\
) 开头,后面跟着 u
或 U
,分别是四位或八位十六进制数字。对可能使用的特定十六进制数字序列有一些限制,一些是通用的,另一些是特定于标识符上下文的。但是请注意,语法上,UCN 规定允许出现在标识符中的唯一附加字符是反斜杠; UCN 上下文之外的标识符中也允许出现在 UCN 中的所有其他字符。
因此,从句法上讲并将讨论限制在标准要求标识符中允许使用的字符、下划线、(无重音符号的)拉丁字母、十进制数字和反斜杠是 C 要求必须的唯一字符在标识符中支持。只有在 UCN 的上下文中才需要支持反斜杠,并且标识符中不允许使用所有有效的 UCN。此外,标准不要求支持数字作为标识符的第一个字符。
另一方面,该标准在允许标识符中使用 "other implementation-defined characters" 方面相当宽松,包括作为第一个字符。即使是十进制数字,否则不能作为标识符中的第一个字符,原则上可以根据本条款允许在该位置,由实施自行决定。如果你希望你的代码在实现之间是可移植的,那么你将避免在任何地方依赖这个规定。如果你想知道你的特定实现允许哪些字符,那么你必须查阅它的文档。
每个符合标准的实现都必须记录其关于标准声明为实现定义的每个细节的行为。例如,GCC's documentation 指定在大多数目标体系结构的标识符中允许使用美元符号 ($
)。您自己链接并引用了 Clang 的相同实现定义细节的文档,该文档更加自由——它允许可以通过 UCN 在标识符中表示的所有字符也可以由 UTF-8 字节序列表示。在许多情况下,如果您显示或打印包含此类字节序列的源代码,它们将呈现为单个显示字符。
如前所述,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−BFFFD, C0 −CFFFD, D0000−DFFFD, E0000−EFFFD
这也意味着有几个范围的字符被排除在使用之外。
从你的例子:
- ☎ 是
260E
并且来自 "Miscellaneous Symbols" 块:2600-26FF
这意味着你错过了 all of these
- ❌ 是
274C
并且来自 "Dingbats" 块:2700-27BF
即 all of these 但其中一些是允许的 (2776−2793
)
- ⇧ 是
21E7
并且来自 "Arrows " 块:2190-21FF
这意味着您错过了 all of these
- 〓 是
3013
并且来自 "CJK Symbols and Punctuation" 块:3000-303F
是 all these 但其中一些是允许的。
- 是
1F34E
并且来自 "Miscellaneous Symbols and Pictographs" 块:1F300-1F5FF
这是 all these 实际上应该工作
(也许 clang
有问题吗?顺便说一句,这不会显示在我的家用电脑上 (Ubuntu),但会显示在我的工作电脑 (Win7))
正如其他人提到的,ISO/IEC 9899:2011 的附件 D 列出了对 C11 中的通用字符名称有效的字符的十六进制值。 (我不会在这里重复它。)我一直在寻找关于“为什么”选择这个列表的答案。
字符集标准
首先,有两个定义一组字符的相关标准:ISO/IEC 10646 (defining UCS) and Unicode. To further confuse (or simplify) things, they both define the same characters since the ISO and Unicode keep them synchronized. UCS is essentially just a character map associating values to a set of characters ("repertoire"), while Unicode also gives further definitions such how to compare strings in an alphabetical sorting order (collation), which code points represent "canonically equivalent" characters (normalization), and a bidirectional algorithm 用于如何处理从右向左书写的语言中的字符,等等。
C 中的通用字符名称
通用字符名称 (UCN) 是 C99 中新增的功能 (ISO/IEC 9899:1999)。在“Rationale for International Standard---Programming Languages---C”(Rev. 2, Oct. 1999), the purpose was "to enable the use of any 'native' character in identifiers, string literals and character constants, while retaining the portability objective of C" (sec. 5.2.1). This section continues on about issues of how to encode these characters in C (the \U
and \u
forms versus multibyte characters or native encodings) and policy models of how to deal with it (p.14, see PDF 第 22 页)。
理由
我希望同样的 "rationale" document from 1999 能够给出为什么每个扩展字符范围都被选为 C99 的 UCN 的 acceptable 的原因。基本原理附件一的全部内容是:
Annex I Universal character names for identifiers (normative)
A new feature of C9X.
这不是什么大道理。他们甚至不知道C标准会在哪一年发布,所以就叫“C9X”。稍后的 rationale document from 2003 稍微更有启发性:
Annex D Universal character names for identifiers (normative)
New feature for C99.
The intention is to keep current with ISO/IEC TR 10176.
ISO/IEC TR 10176是《编程语言标准编写指南》。它基本上是编写编程语言标准的人的指南。它包括在编程语言中使用字符集的指南以及“用户定义标识符的推荐扩展指令表”(附件 A)。但 2003 年基本原理文件中的这句话只是“保持最新的意图”,而不是严格遵守 TR 10176 的承诺。
有 ISO/IEC TR 10176:2003 table 个公开可用的字符。字符值参考 ISO 10646。table 将来自多种语言的字符范围分类为“大写”Lu
; “小写字母”Ll
; “数字,十进制数字”Nd
,“标点符号,连接符”Pc
;等。应该清楚这样的分类对编程语言有什么用。
重要的提醒是 TR 10176 是一份技术报告,而不是标准。我在论坛和与其他编程语言(如 Ada、COBOL 和 D 语言)相关的文档中发现了一些对它的引用。大部分讨论都是关于这些语言的标准应该如何紧密地遵循 TR 10176(不是标准)以及抱怨 TR 10176 落后于 ISO 10646 的更新。
也许最有启发性的是文档 WG21/N3146:“C 和 C++ 的扩展标识符字符的建议。”它始于 2010 年对标准机构的评论,建议限制标识符的初始字符。它提到了关于 C 引用 TR 10176 的类似投诉,并根据 Unicode 的标识符和模式语法 和 的限制,就应允许哪些字符作为标识符的初始字符提出了建议XML 的常用语法结构。 WG21/N3146 给出了后来出现在 C11 标准中的建议措辞 ISO/IEC 9899:2011。文档末尾有一个 table,可帮助阐明所选字符范围。
C11 允许和不允许的字符
下面是扩展 标识符字符范围的编译列表。 粗体字 范围是在 C11 中给出的范围(ISO/IEC 9899:2011 Annex D). Some comments are added about the italicized ranges not listed in C11 (i.e. not allowed). They are either marked in WG21/N3146 as disallowed by Unicode's UAX#31 or XML's Common Syntactic Constructs,或被其他一些注释禁止。
00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00C0-00D6, 00D8-00F6, 00F8-00FF:(各种字符,比如阴性的ª和阳性的º序号指示符、带变音符号的元音、数字字符(如上标数字、分数等)
(之前的差距):UAX31 and/or XML 均不允许。 (一般标点符号如«»、货币符号¥£、数学运算符×÷等)
0100-167F:(拉丁文、希腊文、西里尔文、阿拉伯文、泰文、埃塞俄比亚文等---许多其他)
1680: "Ogham 块包含特定脚本 space: "
1681-180D:(欧甘语、他加禄语、蒙古语等)
180E: "蒙古语块包含特定脚本 space"
180F-1FFF:(更多语言...语音、扩展拉丁语和希腊语等)
2000:启动“通用标点符号”块,但允许使用一些:
200B−200D, 202A−202E, 203F−2040, 2054, 2060−206F:(从“通用标点符号”块中选择)
2070−218F:“上标和下标、货币符号、组合符号的变音符号、类字母符号、数字形式”
2190-245F:“箭头、数学运算符、杂项技术、控制图片、光学字符识别”
2460-24FF:“封闭的字母数字”
2500: 开始“方框图、块元素、几何形状”等
2776-2793:(一些标志和带圆圈的标志)
2794-2BFF:(不同的装饰符号集、数学符号、箭头、盲文图案等)
2C00-2DFF, 2E80-2FFF: "Glagolitic, Latin Extended-C, Coptic, Georgian Supplement, Tifinagh, Ethiopic Extended, Cyrillic Extended-A"(也是 CJK 部首补充)
3000:(“中日韩符号和标点符号”开头,允许部分选择)
3004-3007、3021-302F、3031-303F:(允许“CJK 符号和标点符号”)
3040-D7FF:“平假名、片假名”,更多中日韩表意文字、部首等
D800-F8FF:(这启动High and Low Surrogate Areas (number space needed for encodings), and Private Use)
F900-FD3D、FD40-FDCF、FDF0-FE44、FE47-FFFD:选自“CJK Compatibility Ideographs”、“Arabic Presentation Forms”等。
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:WG21/N3146 给出了这些最终范围的基本原理:
The Supplementary Private Use Area extends from F0000 through 10FFFF; both [AltId] and [XML2008] disallow characters in that range.
In addition, [AltId] disallows, as non-characters, the last two code positions of each plane, i.e. every position of the form PFFFE or PFFFF, for any value of P.
C11 附件 D.2 中的“最初不允许的字符范围”是 0300−036F、1DC0−1DFF、20D0−20FF、FE20−FE2F。
将这个 WG21/N3146 放在 C11 标准 的附录 D 旁边,可以推断出它们是如何排列的。例如,数学运算符和标点符号似乎是不允许的。我希望这能阐明“为什么”或“如何”选择允许的字符。
TLDR;版本
- 合法标识符字符的权威来源是 C11 标准ISO/IEC 9899:2011(见附件 D)。
- 此列表基于技术报告 ISO/IEC TR 10176,但有 修改。
根据@Zaibis 的建议(并且与我自己的 answer to What are the valid characters for macro names?, as well as (and other unicode characters) in identifiers not allowed by g++ 相关))...
clang allows a lot of "crazy" characters.. although I have struggled to find much rhyme or reason - as to why some are allowed ( ϟ ツ ⌘ ☁ ½), and others are not (▶︎ ∀ ★ ©).
比如下面都编译A-OK(clang-700.1.76
)
#define ?: // OK (Pile of poo)
#define ■ @end // OK (HALFWIDTH BLACK SQUARE)
#define @interface // 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,仅说明...
... support for extended identifiers in C99 and C++. This feature allows identifiers to contain certain Unicode characters, as specified by the active language standard; these characters can be written directly in the source file using the UTF-8 encoding, or referred to using universal character names (\u00E0, \U000000E0).
所以,我想我是在问.. "active language standard" 是什么,我怎样才能找到合法标识符的权威来源。
我创建 following code 只是为了看看 clang
会用它做什么。在测试的大约 63488 个可能的标识符中,有 23 个发出了警告,9506 个产生了错误。剩下将近 54,000 个有效字符可用于标识符。当然够了,但谁被裁掉了?为什么?
6.4.2 Identifiers
6.4.2.1 General
...
3 Each universal character name in an identifier shall designate a character whose encoding in ISO/IEC 10646 falls into one of the ranges specified in D.1.71) The initial character shall not be a universal character name designating a character whose encoding falls into one of the ranges specified in D.2. An implementation may allow multibyte characters that are not part of the basic source character set to appear in identifiers; which characters and their correspondence to universal character names is implementation-defined.
...
71) On systems in which linkers cannot accept extended characters, an encoding of the universal character name may be used in forming valid external identifiers. For example, some otherwise unused character or sequence of characters may be used to encode the \u in a universal character name. Extended characters may produce a long external identifier.
...
Annex D
(normative)
Universal character names for identifiers
1 This clause lists the hexadecimal code values that are valid in universal character names in identifiers.
D.1 Ranges of characters allowed
1 00A8, 00AA, 00AD, 00AF, 00B2−00B5, 00B7−00BA, 00BC−00BE, 00C0−00D6, 00D8−00F6, 00F8−00FF
2 0100−167F, 1681−180D, 180F−1FFF
3 200B−200D, 202A−202E, 203F−2040, 2054, 2060−206F
4 2070−218F, 2460−24FF, 2776−2793, 2C00−2DFF, 2E80−2FFF
5 3004−3007, 3021−302F, 3031−303F
6 3040−D7FF
7 F900−FD3D, FD40−FDCF, FDF0−FE44, FE47−FFFD
8 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
D.2 Ranges of characters disallowed initially
1 0300−036F, 1DC0−1DFF, 20D0−20FF, FE20−FE2F
根据附录 D.1 解释的 C2011 标准第 6.4.2 节介绍了包括宏名称在内的标识符语法。这些规定规定每个标识符都可以包含下划线、大写和小写拉丁字母、十进制数字、构成 "universal character names"(受限制)、 的字符序列以及实现定义的任何其他字符.
通用字符名称 (UCN) 是 Unicode 转义序列,类似于 Java、Python 和其他一些语言提供的转义序列:它们以反斜杠 (\
) 开头,后面跟着 u
或 U
,分别是四位或八位十六进制数字。对可能使用的特定十六进制数字序列有一些限制,一些是通用的,另一些是特定于标识符上下文的。但是请注意,语法上,UCN 规定允许出现在标识符中的唯一附加字符是反斜杠; UCN 上下文之外的标识符中也允许出现在 UCN 中的所有其他字符。
因此,从句法上讲并将讨论限制在标准要求标识符中允许使用的字符、下划线、(无重音符号的)拉丁字母、十进制数字和反斜杠是 C 要求必须的唯一字符在标识符中支持。只有在 UCN 的上下文中才需要支持反斜杠,并且标识符中不允许使用所有有效的 UCN。此外,标准不要求支持数字作为标识符的第一个字符。
另一方面,该标准在允许标识符中使用 "other implementation-defined characters" 方面相当宽松,包括作为第一个字符。即使是十进制数字,否则不能作为标识符中的第一个字符,原则上可以根据本条款允许在该位置,由实施自行决定。如果你希望你的代码在实现之间是可移植的,那么你将避免在任何地方依赖这个规定。如果你想知道你的特定实现允许哪些字符,那么你必须查阅它的文档。
每个符合标准的实现都必须记录其关于标准声明为实现定义的每个细节的行为。例如,GCC's documentation 指定在大多数目标体系结构的标识符中允许使用美元符号 ($
)。您自己链接并引用了 Clang 的相同实现定义细节的文档,该文档更加自由——它允许可以通过 UCN 在标识符中表示的所有字符也可以由 UTF-8 字节序列表示。在许多情况下,如果您显示或打印包含此类字节序列的源代码,它们将呈现为单个显示字符。
如前所述,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−BFFFD, C0 −CFFFD, D0000−DFFFD, E0000−EFFFD
这也意味着有几个范围的字符被排除在使用之外。
从你的例子:
- ☎ 是
260E
并且来自 "Miscellaneous Symbols" 块:2600-26FF
这意味着你错过了 all of these - ❌ 是
274C
并且来自 "Dingbats" 块:2700-27BF
即 all of these 但其中一些是允许的 (2776−2793
) - ⇧ 是
21E7
并且来自 "Arrows " 块:2190-21FF
这意味着您错过了 all of these - 〓 是
3013
并且来自 "CJK Symbols and Punctuation" 块:3000-303F
是 all these 但其中一些是允许的。 - 是
1F34E
并且来自 "Miscellaneous Symbols and Pictographs" 块:1F300-1F5FF
这是 all these 实际上应该工作
(也许clang
有问题吗?顺便说一句,这不会显示在我的家用电脑上 (Ubuntu),但会显示在我的工作电脑 (Win7))
正如其他人提到的,ISO/IEC 9899:2011 的附件 D 列出了对 C11 中的通用字符名称有效的字符的十六进制值。 (我不会在这里重复它。)我一直在寻找关于“为什么”选择这个列表的答案。
字符集标准
首先,有两个定义一组字符的相关标准:ISO/IEC 10646 (defining UCS) and Unicode. To further confuse (or simplify) things, they both define the same characters since the ISO and Unicode keep them synchronized. UCS is essentially just a character map associating values to a set of characters ("repertoire"), while Unicode also gives further definitions such how to compare strings in an alphabetical sorting order (collation), which code points represent "canonically equivalent" characters (normalization), and a bidirectional algorithm 用于如何处理从右向左书写的语言中的字符,等等。
C 中的通用字符名称
通用字符名称 (UCN) 是 C99 中新增的功能 (ISO/IEC 9899:1999)。在“Rationale for International Standard---Programming Languages---C”(Rev. 2, Oct. 1999), the purpose was "to enable the use of any 'native' character in identifiers, string literals and character constants, while retaining the portability objective of C" (sec. 5.2.1). This section continues on about issues of how to encode these characters in C (the \U
and \u
forms versus multibyte characters or native encodings) and policy models of how to deal with it (p.14, see PDF 第 22 页)。
理由
我希望同样的 "rationale" document from 1999 能够给出为什么每个扩展字符范围都被选为 C99 的 UCN 的 acceptable 的原因。基本原理附件一的全部内容是:
Annex I Universal character names for identifiers (normative)
A new feature of C9X.
这不是什么大道理。他们甚至不知道C标准会在哪一年发布,所以就叫“C9X”。稍后的 rationale document from 2003 稍微更有启发性:
Annex D Universal character names for identifiers (normative)
New feature for C99.
The intention is to keep current with ISO/IEC TR 10176.
ISO/IEC TR 10176是《编程语言标准编写指南》。它基本上是编写编程语言标准的人的指南。它包括在编程语言中使用字符集的指南以及“用户定义标识符的推荐扩展指令表”(附件 A)。但 2003 年基本原理文件中的这句话只是“保持最新的意图”,而不是严格遵守 TR 10176 的承诺。
有 ISO/IEC TR 10176:2003 table 个公开可用的字符。字符值参考 ISO 10646。table 将来自多种语言的字符范围分类为“大写”Lu
; “小写字母”Ll
; “数字,十进制数字”Nd
,“标点符号,连接符”Pc
;等。应该清楚这样的分类对编程语言有什么用。
重要的提醒是 TR 10176 是一份技术报告,而不是标准。我在论坛和与其他编程语言(如 Ada、COBOL 和 D 语言)相关的文档中发现了一些对它的引用。大部分讨论都是关于这些语言的标准应该如何紧密地遵循 TR 10176(不是标准)以及抱怨 TR 10176 落后于 ISO 10646 的更新。
也许最有启发性的是文档 WG21/N3146:“C 和 C++ 的扩展标识符字符的建议。”它始于 2010 年对标准机构的评论,建议限制标识符的初始字符。它提到了关于 C 引用 TR 10176 的类似投诉,并根据 Unicode 的标识符和模式语法 和 的限制,就应允许哪些字符作为标识符的初始字符提出了建议XML 的常用语法结构。 WG21/N3146 给出了后来出现在 C11 标准中的建议措辞 ISO/IEC 9899:2011。文档末尾有一个 table,可帮助阐明所选字符范围。
C11 允许和不允许的字符
下面是扩展 标识符字符范围的编译列表。 粗体字 范围是在 C11 中给出的范围(ISO/IEC 9899:2011 Annex D). Some comments are added about the italicized ranges not listed in C11 (i.e. not allowed). They are either marked in WG21/N3146 as disallowed by Unicode's UAX#31 or XML's Common Syntactic Constructs,或被其他一些注释禁止。
00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00C0-00D6, 00D8-00F6, 00F8-00FF:(各种字符,比如阴性的ª和阳性的º序号指示符、带变音符号的元音、数字字符(如上标数字、分数等)
(之前的差距):UAX31 and/or XML 均不允许。 (一般标点符号如«»、货币符号¥£、数学运算符×÷等)
0100-167F:(拉丁文、希腊文、西里尔文、阿拉伯文、泰文、埃塞俄比亚文等---许多其他)
1680: "Ogham 块包含特定脚本 space: "
1681-180D:(欧甘语、他加禄语、蒙古语等)
180E: "蒙古语块包含特定脚本 space"
180F-1FFF:(更多语言...语音、扩展拉丁语和希腊语等)
2000:启动“通用标点符号”块,但允许使用一些:
200B−200D, 202A−202E, 203F−2040, 2054, 2060−206F:(从“通用标点符号”块中选择)
2070−218F:“上标和下标、货币符号、组合符号的变音符号、类字母符号、数字形式”
2190-245F:“箭头、数学运算符、杂项技术、控制图片、光学字符识别”
2460-24FF:“封闭的字母数字”
2500: 开始“方框图、块元素、几何形状”等
2776-2793:(一些标志和带圆圈的标志)
2794-2BFF:(不同的装饰符号集、数学符号、箭头、盲文图案等)
2C00-2DFF, 2E80-2FFF: "Glagolitic, Latin Extended-C, Coptic, Georgian Supplement, Tifinagh, Ethiopic Extended, Cyrillic Extended-A"(也是 CJK 部首补充)
3000:(“中日韩符号和标点符号”开头,允许部分选择)
3004-3007、3021-302F、3031-303F:(允许“CJK 符号和标点符号”)
3040-D7FF:“平假名、片假名”,更多中日韩表意文字、部首等
D800-F8FF:(这启动High and Low Surrogate Areas (number space needed for encodings), and Private Use)
F900-FD3D、FD40-FDCF、FDF0-FE44、FE47-FFFD:选自“CJK Compatibility Ideographs”、“Arabic Presentation Forms”等。 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:WG21/N3146 给出了这些最终范围的基本原理:
The Supplementary Private Use Area extends from F0000 through 10FFFF; both [AltId] and [XML2008] disallow characters in that range.
In addition, [AltId] disallows, as non-characters, the last two code positions of each plane, i.e. every position of the form PFFFE or PFFFF, for any value of P.
C11 附件 D.2 中的“最初不允许的字符范围”是 0300−036F、1DC0−1DFF、20D0−20FF、FE20−FE2F。
将这个 WG21/N3146 放在 C11 标准 的附录 D 旁边,可以推断出它们是如何排列的。例如,数学运算符和标点符号似乎是不允许的。我希望这能阐明“为什么”或“如何”选择允许的字符。
TLDR;版本
- 合法标识符字符的权威来源是 C11 标准ISO/IEC 9899:2011(见附件 D)。
- 此列表基于技术报告 ISO/IEC TR 10176,但有 修改。