标识符

来自cppreference.com
< c‎ | language


标识符是数字、下划线、小写及大写拉丁字母和以 \u\U 转义记号指定的,属于 XID_Continue 类的 (C23 起) Unicode 字符 (C99 起)的任意长度序列。合法的标识符必须以非数字字符(拉丁字母、下划线或 Unicode 非数字字符 (C99 起)(C23 前)或属于 XID_Start 类的 Unicode 字符 (C23 起))开始。标识符大小写有别(小写和大写字母不同)。每个标识符都应遵守规范形式 C (C23 起)

是否在标识符中允许未处理(未转义)的 Unicode 字符是实现定义的:
char *\U0001f431 = "cat"; // 受支持
char *🐱 = "cat"; // 由实现定义
                  // (比如,Clang 可用,但版本 10 前的 GCC 不可)
                  // C23 中这两种都非良构。Emoji 并非 XID_Start 字符
(C99 起)
(C23 前)
由实现定义的字符,其在 ISO/IEC 10646(Unicode)中的对应代码点具有 XID_Start 或 XID_Continue 属性,可分别作为标识符开头或第一个字符之后的字符。 (C23 起)

标识符能指代下列类型的实体:

宏名或宏形参名以外的每个标识符都拥有作用域,属于一个命名空间,并且可以拥有链接。相同的标识符可以在程序的相异点指代相异实体,或若实体在不同的命名空间中,则可在相同点指代相异实体。

保留标识符

下列标识符被保留,而且不可在程序中声明(这么做会引起未定义行为):

  1. 作为关键词的标识符不能用于其他目的。具体而言,不允许 #define#undef 等同于关键词的标识符。
  2. 所有以一个下划线开始的外部标识符。
  3. 所有以一个下划线后随一个大写字母或另一下划线开始的标识符(这些保留标识符允许库使用大量幕后的非外部宏及函数)。
  4. 标准库所定义的所有外部标识符(在有宿主环境中)。这表示不允许用户提供的外部名称匹配任何库名称,即使是声明等同于库函数的函数也不允许。
  5. 声明为由实现使用或由标准库未来使用所保留的标识符(见后述)。
  6. 声明为被潜在保留并且为实现所提供的标识符(见后述)。 (C23 起)

所有其他标识符均可用。能使用未被保留或潜在保留 (C23 起)的标识符,而无需担心从一个编译器和库移动程序到另一个时发生意料之外的冲突。

注意:C++ 中,在任何位置有双下划线的标识符都被保留;C 中,只有以双下划线开始的标识符被保留。

库中的保留与潜在保留标识符

标准库保留其所提供的每个标识符。拥有外部链接的保留标识符(例如每个标准函数的名字)受到保留,无关乎包含哪个头文件。其他保留标识符在包含任何其所关联的头文件时被保留。

潜在保留的标识符有意为实现和未来标准版本保留。若潜在保留的标识符为实现所提供,则它变为保留标识符。

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

实现不提供的潜在保留标识符不被保留。能声明或定义它们而无未定义行为。然而,这种用法是不可移植的。

(C23 起)

下列标识符为实现或标准库的未来使用保留或潜在保留 (C23 起)

  • 函数名,全部为潜在保留 (C23 起)
    • <complex.h> 中,cerfcerfccexp2cexpm1clog10clog1pclog2clgammactgammacsinpiccospictanpicasinpicacospicatanpiccompoundncpowncpowrcrootncrsqrtcexp10m1cexp10cexp2m1clog10p1clog2p1clogp1 (C23 起) 及其 -f 和 -l 后缀变体 (C99 起)
    • <ctype.h> <wctype.h> (C95 起) 中,以 isto 后随一个小写字母开始的名字
    • <stdlib.h> <inttypes.h> (C23 起) 中,以 str wcs (C23 起) 后随一个小写字母开始的名字
    • <math.h> 中,以 cr_ 开始的名字 (C23 起)
    • <wchar.h> 中,以 wcs 后随一个小写字母开始的名字 (C95 起)
    • <stdatomic.h> 中,以 atomic_ 后随一个小写字母开始的名字 (C11 起)
    • <threads.h> 中,以 cnd_mtx_thrd_tss_ 后随一个小写字母开始的名字 (C11 起)
  • typedef 名,全部为潜在保留 (C23 起)
    • <stdint.h> 中,以 intuint 开始并以 _t 结束的名字 (C99 起)
    • <stdatomic.h> 中,以 atomic_memory_ 后随一个小写字母开始的名字 (C11 起)
    • <threads.h> 中,以 cnd_mtx_thrd_tss_ 后随一个小写字母开始的名字 (C11 起)
  • 宏名
    • <errno.h> 中,以 E 后随一个数字或大写字母开始的名字
    • <fenv.h> 中,以 FE_ 后随一个大写字母开始的名字 (C99 起)
    • <float.h> 中,以 DBL_DEC32_DEC64_DEC128_DEC_FLT_LDBL_ 后随一个大写字母开始的名字;这些标识符为潜在保留 (C23 起)
    • <stdint.h> 中,以 INTUINT 开始并以 _MAX_MIN_WIDTH (C23 起)_C 结束的名字;这些标识符为潜在保留 (C23 起) (C99 起)
    • <inttypes.h> 中,以 PRISCN 后随一个小写字母或字母 X 开始的名字;这些标识符为潜在保留 (C23 起) (C99 起)
    • <locale.h> 中,以 LC_ 后随一个大写字母开始的名字
    • <math.h> 中,以 FP_ 后随一个大写字母开始的名字 (C23 起)
    • <math.h> 中,以 MATH_ 后随一个大写字母开始的名字;这些标识符为潜在保留 (C23 起)
    • <signal.h> 中,以 SIGSIG_ 后随一个大写字母开始的名字
    • <time.h> 中,以 TIME_ 后随一个大写字母开始的名字 (C11 起)
    • <stdatomic.h> 中,以 ATOMIC_ 后随一个大写字母开始的名字;这些标识符为潜在保留 (C23 起) (C11 起)
  • 枚举常量,全部为潜在保留 (C23 起)
    • <stdatomic.h> 中,以 memory_order_ 后随一个小写字母开始的名字 (C11 起)
    • <threads.h> 中,以 cnd_mtx_thrd_tss_ 后随一个小写字母开始的名字 (C11 起)

推荐实现在声明或定义潜在保留标识符时警告,除了当

  • 声明为实现所提供的拥有外部链接的标识符的非定义声明,且
  • 声明中使用的类型与定义中的兼容
(C23 起)

翻译限制

尽管标识符长度上无特定的限制,一些早期编译器还是在标识符中的有效起始字符数上有限制,而链接器在带外部链接的名称上加上了更严格的限制。C 要求任何服从标准的实现支持下列极限:

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

引用

  • C17 标准(ISO/IEC 9899:2018):
  • 5.2.4.1 Translation limits (第 19-20 页)
  • 6.4.2 Identifiers (第 43 页)
  • 6.10.8 Predefined macro names (第 127-129 页)
  • 6.11.9 Predefined macro names (第 130 页)
  • 7.31 Future library directions (第 332-333 页)
  • K.3.1.2 Reserved identifiers (第 425 页)
  • C11 标准(ISO/IEC 9899:2011):
  • 5.2.4.1 Translation limits (第 25-26 页)
  • 6.4.2 Identifiers (第 59-60 页)
  • 6.10.8 Predefined macro names (第 175-176 页)
  • 6.11.9 Predefined macro names (第 179 页)
  • 7.31 Future library directions (第 455-457 页)
  • K.3.1.2 Reserved identifiers (第 584 页)
  • C99 标准(ISO/IEC 9899:1999):
  • 5.2.4.1 Translation limits (第 20-21 页)
  • 6.4.2 Identifiers (第 51-52 页)
  • 6.10.8 Predefined macro names (第 160-161 页)
  • 6.11.9 Predefined macro names (第 163 页)
  • 7.26 Future library directions (第 401-402 页)
  • C89/C90 标准(ISO/IEC 9899:1990):
  • 2.2.4.1 Translation limits
  • 3.1.2 Identifiers
  • 3.8.8 Predefined macro names

参阅