首页 文章

在C标识符中使用下划线有哪些规则?

提问于
浏览
828

它's common in C++ to name member variables with some kind of prefix to denote the fact that they'重新成员变量,而不是局部变量或参数 . 如果你_1112754_ ll可能使用 m_foo . 我偶尔也见过 myFoo .

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

5 回答

  • 757

    规则(在C 11中没有变化):

    • 保留在任何范围内,包括用作implementation宏:

    • 标识符以下划线开头,后面紧跟大写字母
      包含相邻下划线的

    • 标识符(或"double underscore")

    • 在全局命名空间中保留:

    • 标识符以下划线开头

    • 此外, std 命名空间中的所有内容都是保留的 . (但是,您可以添加模板特化 . )

    从2003 C标准:

    17.4.3.1.2全局名称[lib.global.names]某些名称和函数签名集始终保留给实现:每个名称包含双下划线(__)或以下划线后跟大写字母开头( 2.11)保留给任何用途的实施 . 以下划线开头的每个名称都保留给实现,以用作全局名称空间中的名称 . 165)此类名称也在namespace :: 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)具有外部链接的保留标识符列表包括errno,math_errhandling,setjmp和va_end .

    其他限制可能适用 . 例如,POSIX标准保留了许多可能在正常代码中显示的标识符:

    • 以大写 E 开头的名称后跟一个数字或大写字母:

    • 可用于其他错误代码名称 .

    • isto 开头,后跟小写字母的名称

    • 可用于其他字符测试和转换功能 .

    • LC_ 开头,后跟大写字母的名称

    • 可用于指定区域设置属性的其他宏 .

    • 保留 fl 后缀的所有现有数学函数的名称

    • 分别用于对float和long double参数进行操作的相应函数 .

    • 保留以 SIG 开头,后跟大写字母的名称

    • 用于其他信号名称 .

    • 保留以 SIG_ 开头,后跟大写字母的名称

    • 用于其他信号操作 .

    • strmemwcs 开头,后跟小写字母的名称被保留

    • 用于其他字符串和数组函数 .

    • PRISCN 开头,后跟任何小写字母或 X 的名称保留

    • 用于其他格式说明符宏

    • _t 结尾的名称被保留

    • 用于其他类型名称 .

    虽然现在将这些名称用于您自己的目的可能不会导致问题,但它们确实会增加与该标准的未来版本冲突的可能性 .


    就个人而言,我只是不用下划线开始标识符 . 我的规则的新增内容:不要使用双重下划线,这很容易,因为我很少使用下划线 .

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

    任何以 _t 结尾的标识符的规则都让我感到很惊讶 . 我认为这是一个POSIX标准(尚不确定)寻找澄清和官方章节和经文 . 这是来自GNU libtool manual,列出保留名称 .

    CesarB提供了以下POSIX 2004保留符号的链接和注释'that many other reserved prefixes and suffixes ... can be found there' . POSIX 2008保留符号在此处定义 . 这些限制比上述限制更微妙 .

  • 32

    避免名称冲突的规则都在C标准中(参见Stroustrup书)并由C大师(Sutter等)提及 .

    个人规则

    因为我不想处理案例,并且想要一个简单的规则,我设计了一个既简单又正确的 personal

    When naming a symbol, you will avoid collision with compiler/OS/standard libraries if you:


    never start a symbol with an underscore never name a symbol with two consecutive underscores inside.

    当然,将代码放在一个唯一的命名空间中也有助于避免冲突(但不能防止恶意宏)

    一些例子

    (我使用宏,因为它们是更多的C / C符号的代码污染,但它可以是从变量名到类名的任何东西)

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

    从C 0x草稿中提取

    n3242.pdf文件(我希望最终的标准文本类似):

    17.6.3.3.2全局名称[global.names]某些名称和函数签名集始终保留给实现: - 每个名称包含双下划线_ _或以下划线开头,后跟大写字母(2.12)保留给任何用途的实现 . - 以下划线开头的每个名称都保留给实现,以用作全局名称空间中的名称 .

    但是也:

    17.6.3.3.5用户定义的文字后缀[usrlit.suffix]不以下划线开头的文字后缀标识符保留用于将来的标准化 .

    这最后一个条款令人困惑,除非您认为如果未在全局命名空间中定义,以一个下划线开头并后跟小写字母的名称将为Ok ...

  • 22

    来自MSDN

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

    这意味着您可以使用单个下划线作为成员变量前缀,只要它后面跟一个小写字母 .

    这显然取自C标准的第17.4.3.1.2节,但我无法在线找到完整标准的原始来源 .

    另见this question .

  • 177

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

    我甚至在类和名称空间内执行此操作,因为我只需要记住一条规则(与“在全局范围内的名称末尾,以及其他地方名称的开头”相比) .

  • 2

    是的,可以在标识符的任何地方使用下划线 . 我相信规则是:第一个字符中的任何a-z,A-Z,_和后续字符的0-9 .

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

相关问题