Namespaces
Variants

Identifier

From cppreference.net

标识符 是由数字、下划线、小写和大写拉丁字母 ,以及使用 \u \U 转义 符号指定的Unicode字符 (C99起) ,以及属于 XID_Continue 类别的字符 (C23起) 组成的任意长度序列。有效的标识符必须以非数字字符(拉丁字母、下划线 或Unicode非数字字符 (C99起) (C23前) ,或属于 XID_Start 类别的Unicode字符 (C23起) )开头。标识符区分大小写(小写和大写字母被视为不同字符)。 所有标识符必须符合 规范化形式C 的要求。 (C23起)

是否允许在标识符中使用原始(未转义)Unicode字符由实现定义:
char *\U0001f431 = "cat"; // 支持
char *🐱 = "cat"; // 由实现定义
                  // (例如在 Clang 中可用,但 GCC 10 之前版本不可用)
                  // 两者在 C23 中均为不合规形式。表情符号不属于 XID_Start 字符
(自 C99 起)
(直至 C23)
其对应码位在 ISO/IEC 10646 (Unicode) 中具有 XID_Start 或 XID_Continue 属性的实现定义字符,可分别出现在标识符的首字符或首字符之后。 (自 C23 起)

标识符可表示以下类型的实体:

除宏名称或宏参数名称外的每个标识符都具有 作用域 ,属于某个 命名空间 ,并可能具有 链接 。同一标识符在程序的不同位置可能表示不同实体,若实体处于不同命名空间中,即使在相同位置也可能表示不同实体。

目录

保留标识符

以下标识符是 保留的 ,不能在程序中声明(否则会引发未定义行为):

  1. 标识符中属于 关键字 的部分不能用于其他用途。特别是不允许对与关键字完全相同的标识符进行 #define 或 #undef 操作。
  2. 所有以下划线开头的外部标识符。
  3. 所有以下划线后接大写字母或另一个下划线开头的标识符(这些保留标识符允许库使用大量内部非外部宏和函数)。
  4. 标准库定义的所有外部标识符(在托管环境中)。这意味着不允许任何用户提供的外部名称与任何库名称匹配,即使声明与库函数完全相同的函数也不允许。
  5. 声明为保留给实现或标准库未来使用的标识符(见下文)。
  6. 声明为可能保留并由实现提供的标识符(见下文)。 (since C23)

所有其他标识符均可使用。非保留 或潜在保留 (C23起) 的标识符可以放心使用,在将程序从一个编译器和库迁移到另一个时不会出现意外的命名冲突。

注意:在C++中,任何位置包含双下划线的标识符在所有地方都是保留的;而在C语言中,只有以双下划线开头的标识符才是保留的。

库中保留及潜在保留标识符

标准库保留其提供的所有标识符。具有 外部链接 的保留标识符(例如所有标准函数名称)无论包含哪个头文件均被保留。其他保留标识符在其关联头文件被包含时即被保留。

潜在保留标识符旨在供实现和标准的未来修订版本使用。如果实现提供了潜在保留标识符,则该标识符将成为保留标识符。

实现仅允许提供作为函数名保留的潜在保留标识符的 外部定义

实现未提供的潜在保留标识符不属于保留标识符。用户可以声明或定义这些标识符而不会引发未定义行为。但此类用法不具备可移植性。

(since C23)

以下标识符被保留 或可能被保留 (since C23) ,供实现或标准库未来使用。

  • 函数名 ,所有这些都可能被保留 (自 C23 起)
    • cerf , cerfc , cexp2 , cexpm1 , clog10 , clog1p , clog2 , clgamma , ctgamma , csinpi , ccospi , ctanpi , casinpi , cacospi , catanpi , ccompoundn , cpown , cpowr , crootn , crsqrt , cexp10m1 , cexp10 , cexp2m1 , clog10p1 , clog2p1 , clogp1 (自 C23 起) 及其带 -f 和 -l 后缀的变体,位于 <complex.h> (自 C99 起)
    • is to 开头后接小写字母,位于 <ctype.h> <wctype.h> (自 C95 起)
    • str wcs (自 C23 起) 开头后接小写字母,位于 <stdlib.h> <inttypes.h> (自 C23 起)
    • cr_ 开头,位于 <math.h> (自 C23 起)
    • wcs 开头后接小写字母,位于 <wchar.h> (自 C95 起)
    • atomic_ 开头后接小写字母,位于 <stdatomic.h> (自 C11 起)
    • cnd_ , mtx_ , thrd_ tss_ 开头后接小写字母,位于 <threads.h> (自 C11 起)
  • 类型定义名 ,所有这些都可能被保留 (自 C23 起)
    • int uint 开头并以 _t 结尾,位于 <stdint.h> (自 C99 起)
    • atomic_ memory_ 开头后接小写字母,位于 <stdatomic.h> (自 C11 起)
    • cnd_ , mtx_ , thrd_ tss_ 开头后接小写字母,位于 <threads.h> (自 C11 起)
  • 宏名
    • E 开头后接数字或大写字母,位于 <errno.h>
    • FE_ 开头后接大写字母,位于 <fenv.h> (自 C99 起)
    • DBL_ , DEC32_ , DEC64_ , DEC128_ , DEC_ , FLT_ LDBL_ 开头后接大写字母,位于 <float.h> ;这些标识符可能被保留 (自 C23 起)
    • INT UINT 开头并以 _MAX , _MIN , _WIDTH (自 C23 起) _C 结尾,位于 <stdint.h> ;这些标识符可能被保留 (自 C23 起) (自 C99 起)
    • PRI SCN 开头后接小写字母或字母 X ,位于 <inttypes.h> ;这些标识符可能被保留 (自 C23 起) (自 C99 起)
    • LC_ 开头后接大写字母,位于 <locale.h>
    • FP_ 开头后接大写字母,位于 <math.h> (自 C23 起)
    • MATH_ 开头后接大写字母,位于 <math.h> ;这些标识符可能被保留 (自 C23 起)
    • SIG SIG_ 开头后接大写字母,位于 <signal.h>
    • TIME_ 开头后接大写字母,位于 <time.h> (自 C11 起)
    • ATOMIC_ 开头后接大写字母,位于 <stdatomic.h> ;这些标识符可能被保留 (自 C23 起) (自 C11 起)
  • 枚举常量 ,所有这些都可能被保留 (自 C23 起)
    • memory_order_ 开头后接小写字母,位于 <stdatomic.h> (自 C11 起)
    • cnd_ , mtx_ , thrd_ tss_ 开头后接小写字母,位于 <threads.h> (自 C11 起)

建议实现在声明或定义潜在保留标识符时发出警告,除非满足以下情况:

  • 该声明是由实现提供、具有外部链接的标识符的非定义声明,且
  • 声明中使用的类型与定义中使用的类型 兼容
(since C23)

翻译限制

尽管标识符的长度没有具体限制,但早期编译器对标识符中有效初始字符的数量存在限制,且链接器对具有 外部链接 的名称施加了更严格的限制。C语言要求任何符合标准的实现至少需支持以下限制:

  • 内部标识符或宏名称中31个有效初始字符
  • 外部标识符中6个有效初始字符
  • 一个翻译单元中511个外部标识符
  • 一个块中声明的127个具有块作用域的标识符
  • 一个预处理翻译单元中同时定义的1024个宏标识符
(C99前)
  • 内部标识符或宏名称中63个有效初始字符
  • 外部标识符中31个有效初始字符
  • 一个翻译单元中4095个外部标识符
  • 一个块中声明的511个具有块作用域的标识符
  • 一个预处理翻译单元中同时定义的4095个宏标识符
(C99起)

参考文献

  • C23 标准 (ISO/IEC 9899:2024):
  • 5.2.5.2 翻译限制 (p: TBD)
  • 6.4.2 标识符 (p: TBD)
  • 6.10.10 预定义宏名 (p: TBD)
  • 6.11.7 预定义宏名 (p: TBD)
  • 7.33 未来库方向 (p: TBD)
  • K.3.1.2 保留标识符 (p: TBD)
  • C17 标准 (ISO/IEC 9899:2018):
  • 5.2.4.1 翻译限制 (页: 19-20)
  • 6.4.2 标识符 (页: 43)
  • 6.10.8 预定义宏名称 (页: 127-129)
  • 6.11.9 预定义宏名称 (页: 130)
  • 7.31 未来库方向 (页: 332-333)
  • K.3.1.2 保留标识符 (页: 425)
  • C11 标准 (ISO/IEC 9899:2011):
  • 5.2.4.1 翻译限制 (p: 25-26)
  • 6.4.2 标识符 (p: 59-60)
  • 6.10.8 预定义宏名称 (p: 175-176)
  • 6.11.9 预定义宏名称 (p: 179)
  • 7.31 未来库方向 (p: 455-457)
  • K.3.1.2 保留标识符 (p: 584)
  • C99标准(ISO/IEC 9899:1999):
  • 5.2.4.1 翻译限制(页码:20-21)
  • 6.4.2 标识符(页码:51-52)
  • 6.10.8 预定义宏名(页码:160-161)
  • 6.11.9 预定义宏名(页码:163)
  • 7.26 未来库发展方向(页码:401-402)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 2.2.4.1 翻译限制
  • 3.1.2 标识符
  • 3.8.8 预定义宏名称

参见

C++ 文档 关于 标识符