在 C 标识符中使用下划线的规则是什么?
What are the rules about using an underscore in a C identifier?
在 C(和其他语言)中为变量和函数的名称使用前缀和后缀是很常见的。特别是,偶尔会看到在“适当的”标识符之前或之后使用下划线,例如_x
和 _y
变量,或 _print
等。但是,还有避免名称以下划线开头的常识,以免与 C 标准库实现冲突。
那么,在什么地方、什么地方可以使用下划线呢?
足够好的经验法则
Don't start your identifier with an underscore.
就是这样。您可能仍然与某些特定于文件的定义有冲突(见下文),但这些只会给您一条错误消息,您可以自行处理。
安全,略有限制,经验法则
Don't start your identifier with:
- An underscore.
- Any 1-3 letter prefix, followed by an underscore, which isn't a proper word (e.g.
a_
, st_
)
memory_
or atomic_
.
and don't end your identifier with either _MIN
or _MAX
.
此规则涵盖的内容比实际保留的要多,但更容易记住。
更详细的规则
这是基于C2x standard draft (and thus covers previous standards' reservations) and the glibc documentation。
不要使用:
- 前缀
__
(两个下划线)。
- 一个下划线后跟一个大写字母的前缀(例如
_D
)。
- 对于在文件范围内可见的标识符 - 前缀
_
.
- 以下带下划线的前缀,当后跟小写字母时:
atomic_
、memory_
、memory_order_
、cnd_
、mtx_
、thrd_
, tss_
- 以下带下划线的前缀,后跟大写字符:
LC_
、SIG_
、ATOMIC
、TIME_
- 后缀
_t
(这是一个 POSIX 限制;对于 C 本身,您可以使用此后缀,除非您的标识符以 int
或 uint
开头)
附加限制是每个库头文件而不是通用的(其中一些是 POSIX 限制):
If you use header file...
You can't use identifiers with ...
dirent.h
Prefix d_
fcntl.h
Prefixes l_
, F_
, O_
, and S_
grp.h
Prefix gr_
limits.h
Suffix _MAX
(also probably _MIN
)
pwd.h
Prefix pw_
signal.h
Prefixes sa_
and SA_
sys/stat.h
Prefixes st_
and S_
sys/times.h
Prefix tms_
termios.h
Prefix c_
当然还有不涉及下划线的额外限制。
C 标准,库章节,保留某些标识符(强调我的):
C17 7.1.3 保留标识符
— All identifiers that begin with an underscore and either an uppercase letter or another
underscore are always reserved for any use.
— All identifiers that begin with an underscore are always reserved for use as identifiers
with file scope in both the ordinary and tag name spaces.
— Each macro name in any of the following subclauses (including the future library
directions) is reserved for use as specified if any of its associated headers is included;
unless explicitly stated otherwise (see 7.1.4).
— All identifiers with external linkage in any of the following subclauses (including the
future library directions) and errno are always reserved for use as identifiers with
external linkage.184)
— Each identifier with file scope listed in any of the following subclauses (including the
future library directions) is reserved for use as a macro name and as an identifier with
file scope in the same name space if any of its associated headers is included.
其中“为任何用途保留”是指为 compiler/standard 库保留,请参阅 “为实施保留”也意味着为 compiler/standard 库保留。
此外,未来的库方向C17.31保留了很多标识符-这是一个很大的章节,我只引用最值得注意的部分:
7.31.10 Integer types <stdint.h>
Typedef names beginning with int or uint and ending with _t may be added to the
types defined in the <stdint.h> header. Macro names beginning with INT or UINT
and ending with _MAX, _MIN, or _C may be added to the macros defined in the
<stdint.h> header.
7.31.12 General utilities <stdlib.h>
Function names that begin with str and a lowercase letter may be added to the
declarations in the <stdlib.h> header.
7.31.13 String handling <string.h>
Function names that begin with str, mem, or wcs and a lowercase letter may be added to the declarations in the <string.h> header.
直接回答你的问题:
So, where and where is it ok to use underscores?
严格来说:无处可去。你永远不应该声明以下划线开头的标识符,因为它们可能与标准库或语言关键字等冲突。尽管如上面粗体文本所暗示的那样,你可以在本地命名空间中使用一个下划线后跟一个小写字母。
在 C(和其他语言)中为变量和函数的名称使用前缀和后缀是很常见的。特别是,偶尔会看到在“适当的”标识符之前或之后使用下划线,例如_x
和 _y
变量,或 _print
等。但是,还有避免名称以下划线开头的常识,以免与 C 标准库实现冲突。
那么,在什么地方、什么地方可以使用下划线呢?
足够好的经验法则
Don't start your identifier with an underscore.
就是这样。您可能仍然与某些特定于文件的定义有冲突(见下文),但这些只会给您一条错误消息,您可以自行处理。
安全,略有限制,经验法则
Don't start your identifier with:
- An underscore.
- Any 1-3 letter prefix, followed by an underscore, which isn't a proper word (e.g.
a_
,st_
)memory_
oratomic_
.and don't end your identifier with either
_MIN
or_MAX
.
此规则涵盖的内容比实际保留的要多,但更容易记住。
更详细的规则
这是基于C2x standard draft (and thus covers previous standards' reservations) and the glibc documentation。
不要使用:
- 前缀
__
(两个下划线)。 - 一个下划线后跟一个大写字母的前缀(例如
_D
)。 - 对于在文件范围内可见的标识符 - 前缀
_
. - 以下带下划线的前缀,当后跟小写字母时:
atomic_
、memory_
、memory_order_
、cnd_
、mtx_
、thrd_
,tss_
- 以下带下划线的前缀,后跟大写字符:
LC_
、SIG_
、ATOMIC
、TIME_
- 后缀
_t
(这是一个 POSIX 限制;对于 C 本身,您可以使用此后缀,除非您的标识符以int
或uint
开头)
附加限制是每个库头文件而不是通用的(其中一些是 POSIX 限制):
If you use header file... | You can't use identifiers with ... |
---|---|
dirent.h |
Prefix d_ |
fcntl.h |
Prefixes l_ , F_ , O_ , and S_ |
grp.h |
Prefix gr_ |
limits.h |
Suffix _MAX (also probably _MIN ) |
pwd.h |
Prefix pw_ |
signal.h |
Prefixes sa_ and SA_ |
sys/stat.h |
Prefixes st_ and S_ |
sys/times.h |
Prefix tms_ |
termios.h |
Prefix c_ |
当然还有不涉及下划线的额外限制。
C 标准,库章节,保留某些标识符(强调我的):
C17 7.1.3 保留标识符
— All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
— All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.
— Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).
— All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage.184)
— Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.
其中“为任何用途保留”是指为 compiler/standard 库保留,请参阅
此外,未来的库方向C17.31保留了很多标识符-这是一个很大的章节,我只引用最值得注意的部分:
7.31.10 Integer types <stdint.h> Typedef names beginning with int or uint and ending with _t may be added to the types defined in the <stdint.h> header. Macro names beginning with INT or UINT and ending with _MAX, _MIN, or _C may be added to the macros defined in the <stdint.h> header.
7.31.12 General utilities <stdlib.h>
Function names that begin with str and a lowercase letter may be added to the declarations in the <stdlib.h> header.7.31.13 String handling <string.h>
Function names that begin with str, mem, or wcs and a lowercase letter may be added to the declarations in the <string.h> header.
直接回答你的问题:
So, where and where is it ok to use underscores?
严格来说:无处可去。你永远不应该声明以下划线开头的标识符,因为它们可能与标准库或语言关键字等冲突。尽管如上面粗体文本所暗示的那样,你可以在本地命名空间中使用一个下划线后跟一个小写字母。