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

在 C ++ 中,通常使用某种前缀来命名成员变量,以表示它们是成员变量,而不是局部变量或参数。如果您来自 MFC 背景,则可能会使用m_foo 。我也偶尔见过myFoo

C#(或者可能只是. NET)似乎建议仅使用下划线,例如_foo 。 C ++ 标准允许吗?

答案

规则(在 C ++ 11 中未更改):

  • 在任何范围内都保留,包括用作实现宏:
    • 以下划线开头的标识符,紧随其后的是大写字母
    • 包含相邻下划线(或 “双下划线”)的标识符
  • 在全局名称空间中保留:
    • 以下划线开头的标识符
  • 同样, std名称空间中的所有内容均保留。 (不过,您可以添加模板专长。)

根据 2003 C ++ 标准:

17.4.3.1.2 全局名称 [lib.global.names]

某些名称和函数签名集始终保留给实现:

  • 每个包含双下划线( __ )或以下划线后跟大写字母(2.11)开头的名称都保留给实现以供任何使用。
  • 每个以下划线开头的名称都保留给实现,以用作全局名称空间中的名称。 165

165)这样的名称也在名称空间::std (17.4.3.1)中保留。

因为 C ++ 基于 C 标准(1.1 / 2,C ++ 03),而 C99 是规范性引用(1.2 / 1,C ++ 03),这些也适用于 1999 C 标准:

7.1.3 保留标识符

每个头声明或定义在其关联的子节中列出的所有标识符,并可选地声明或定义在其关联的将来的库指示子节中列出的标识符以及始终保留用于任何用途或用作文件范围标识符的标识符。

  • 所有以下划线,大写字母或另一个下划线开头的标识符始终保留供任何使用。
  • 在普通和标记名称空间中,所有以下划线开头的标识符始终保留为文件范围的标识符。
  • 如果包含任何关联的标头,则以下任何一个子节(包括将来的库说明)中的每个宏名均保留用于指定用途。除非另有明确说明(参见 7.1.4)。
  • 在以下任何条款(包括将来的库说明)中,所有具有外部链接的标识符始终保留为具有外部链接的标识符。 154
  • 在以下任何一个子节(包括将来的库说明)中列出的每个具有文件范围的标识符都保留用作宏名,并且如果包含任何关联的标头,则在同一名称空间中用作具有文件范围的标识符。

没有其他标识符保留。如果程序在保留它的上下文中声明或定义标识符(而不是 7.1.4 允许),或者将保留标识符定义为宏名,则该行为未定义。

如果程序删除(使用#undef )上面列出的第一组中标识符的任何宏定义,则该行为未定义。

154)具有外部链接的保留标识符的列表包括errnomath_errhandlingsetjmpva_end

其他限制可能适用。例如,POSIX 标准保留了很多可能以普通代码显示的标识符:

  • 以大写E开头的名称后跟数字或大写字母:
    • 可以用于其他错误代码名称。
  • isto开头的小写字母
    • 可以用于其他字符测试和转换功能。
  • LC_开头的名称,后跟一个大写字母
    • 可以用于指定区域设置属性的其他宏。
  • 保留所有以fl结尾的现有数学函数的名称
    • 对于分别对 float 和 long double 参数运行的相应函数。
  • 保留以SIG开头且后跟大写字母的名称
    • 有关其他信号名称。
  • 保留以SIG_开头,大写字母的名称
    • 用于其他信号动作。
  • strmemwcs开头,后跟小写字母的名称被保留
    • 用于其他字符串和数组函数。
  • 保留以PRISCN开头的名称,后跟任何小写字母或X
    • 用于其他格式说明符宏
  • _t结尾的名称被保留
    • 用于其他类型名称。

尽管现在将这些名称用于您自己的目的可能不会引起问题,但它们确实增加了与该标准的未来版本冲突的可能性。


我个人只是不以下划线开头标识符。我的规则的新增功能:不要在任何地方使用双下划线,这很容易,因为我很少使用下划线。

在对本文进行研究之后,我不再用_t结尾标识符,因为这是 POSIX 标准保留的。

关于以_t结尾的任何标识符的规则使我感到非常惊讶。我认为这是 POSIX 标准(尚不确定),需要澄清和官方章节。这来自GNU libtool 手册 ,其中列出了保留名称。

CesarB 提供了指向POSIX 2004保留符号的以下链接,并指出 “在此可以找到许多其他保留的前缀和后缀...”。此处定义了POSIX 2008保留符号。这些限制比上述限制更加细微。

#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT

MSDN

在所有范围内,C ++ 实现均保留在标识符的开头使用两个连续的下划线字符(__)或使用单个下划线后跟一个大写字母。对于具有文件范围的名称,应避免使用前导下划线,后跟小写字母,因为这可能与当前或将来的保留标识符冲突。

这意味着您可以使用单个下划线作为成员变量前缀,只要后面带有小写字母即可。

这显然取自 C ++ 标准的 17.4.3.1.2 节,但是我找不到在线完整标准的原始资料。

另请参阅此问题

至于问题的另一部分,通常将下划线放在变量名的末尾 ,以免与内部任何内容发生冲突。

我什至在类和名称空间中也可以这样做,因为我只需要记住一个规则(与 “在全局范围内名称的末尾,在其他地方名称的开头” 相比)。

是的,下划线可以在标识符的任何地方使用。我相信规则是:第一个字符中的 az,AZ,_中的任何一个,后几个字符中的 + 0-9。

下划线前缀在 C 代码中很常见 - 单个下划线表示 “专用”,通常保留双下划线以供编译器使用。