在C标识符中使用下划线的规则是什么?

d7v8vwbk  于 2023-04-29  发布在  其他
关注(0)|答案(3)|浏览(135)

在C(和其他语言)中,使用前缀和后缀作为变量和函数的名称是很常见的。特别是,人们偶尔会看到下划线的使用,在“适当”标识符之前或之后,例如。例如_x_y变量,或_print等。但是,还有一个共同的智慧,即避免名称以下划线开头,以免与C标准库实现冲突。
那么,在哪里和哪里可以使用下划线?

wa7juj8i

wa7juj8i1#

足够好的经验法则

不要以下划线开始标识符。

就是这样,你可能仍然会与一些文件特定的定义发生冲突(见下文),但这些定义只会给你一个错误消息,你可以处理。

安全,略有限制,经验法则

不要以下列内容作为标识符的开头:

  • 下划线。
  • 任何1-3个字母的前缀,后面跟着一个下划线,这不是一个正确的词(e。例如a_st_
  • memory_atomic_

不要以_MIN_MAX结束标识符。
这些规则禁止比实际保留的多一点的内容,但相对容易记住。

更详细的规则

这是基于C2x standard draft(因此涵盖了以前标准的保留)和glibc documentation
不要用途:

  • 前缀__(两个下划线)。
  • 一个下划线后跟一个大写字母的前缀(e。例如_D)。
  • 对于在文件范围内可见的标识符-前缀_
  • 下面的前缀带有下划线,后跟小写字母:atomic_memory_memory_order_cnd_mtx_thrd_tss_
  • 以下前缀带有下划线,后跟大写字母时:LC_SIG_ATOMICTIME_
  • 后缀_t(这是POSIX限制;对于正确的C,除非标识符以intuint开头,否则可以使用此后缀)

其他限制是针对每个库头文件的,而不是通用的(其中一些是POSIX限制):
| 如果使用头文件。..|不能与一起使用标识符。..|
| --------------|--------------|
| dirent.h|前缀d_|
| fcntl.h|前缀l_F_O_S_|
| grp.h|前缀gr_|
| limits.h|后缀_MAX(也可能是_MIN)|
| pwd.h|前缀pw_|
| signal.h|前缀sa_SA_|
| sys/stat.h|前缀st_S_|
| sys/times.h|前缀tms_|
| termios.h|前缀c_|
当然,还有一些不涉及下划线的附加限制。

eit6fx6z

eit6fx6z2#

C标准的库章节保留了某些标识符(重点是我的):

C17 7.1.3预留标识
**-所有以下划线和大写字母或另一个下划线开始的标识符始终保留用于任何用途。

  • 所有以下划线开始的标识符始终保留用作普通名称空间和标记名称空间中文件范围的标识符。**
  • 如果包含任何相关的标题,则保留以下任何子条款(包括未来的库方向)中的每个宏名称,以供指定使用;除非另有明确说明(见7.1.4)。
  • 以下任何子条款(包括未来的库方向)和errno中的所有具有外部链接的标识符始终保留用作具有外部链接的标识符。184)
  • 以下任何子条款(包括未来的库方向)中列出的具有文件范围的每个标识符都保留用作宏名称,并且如果包含任何相关的标头,则用作同一名称空间中具有文件范围的标识符。
    其中“保留用于任何用途”表示为编译器/标准库保留,参见What's the meaning of "reserved for any use"?“保留用于实现”也表示为编译器/标准库保留。
    此外,未来图书馆方向C17。31保留了很多标识符-这是一个很大的章节,我只引用最值得注意的部分:
    7.31.10整数类型<stdint.h>以int或uint开头,以_t结尾的Typedef名称可以添加到头文件中定义的类型<stdint.h>。以INT或UINT开头,以_MAX,_MIN或_C结尾的宏名称可以添加到头文件中定义的宏<stdint.h>。
    7.31.12一般公用设施<stdlib.h>
    以str和小写字母开始的函数名可以添加到头部的声明中<stdlib.h>。
    7.31.13字符串处理<string.h>
    以str、mem或wcs和小写字母开始的函数名可以添加到标头的声明中<string.h>。
    直接回答您的问题:
    那么,在哪里和哪里可以使用下划线?
    严格地说:你不应该声明以下划线开头的标识符,因为它们可能与标准库或语言关键字等冲突。尽管从上面的粗体文本中可以看出,您可以在本地名称空间中使用一个下划线后跟小写字母。
tcomlyy6

tcomlyy63#

在没有保留标识符的情况下,添加任何新的保留字或预定义标识符将冒着破坏可能碰巧使用这些标识符的现有代码的风险。保留名称类别的目的是允许通过标准、编译器扩展、标准库头内部或其他库头内部添加这些功能,而不必确定某些现有代码是否可能已经在使用标识符。
然而,请注意,虽然不能保证标准不会定义标识符__WOOZLELIB_FNORD,但标准的作者不太可能选择包含“WOOZLELIB”的名称用于任何目的,而不是标准化Woozle库分配给它的功能。虽然理论上标准可能会添加一个函数来确定字符串是否感到愤怒并称之为“陌生人”[“字符串愤怒”],但标准并不打算促进对此类事情的偏执。

相关问题