CottLi
3/11/2020 - 3:50 AM

标识符命名

C语言命名规则

C是一门朴素的语言,你使用的命名也应该这样。与Modula-2和Pascal程序员不同,C程序员不使用诸如“ThisVariableIsATemporaryCounter”这样“聪明”的名字。C程序员应该叫它“tmp”,这写起来更简单,也不会更难懂。

然而,当面对复杂情况时就有些棘手,给全局变量取一个描述性的名字是必要的。把一个全局函数叫做“foo”是一种目光短浅的行为。全局函数也一样,如果你有一个统计当前用户个数的函数,应当把它命名为“count_active_user()”或者简单点些的类似名称,不应该命名为“cntusr()”。

三种流行的命名法则

目前,业界共有四种命名法则:驼峰命名法、匈牙利命名法、帕斯卡命名法和下划线命名法,其中前三种是较为流行的命名法。

  1. 驼峰命令法。正如它的名称所表示的那样,是指混合使用大小写字母来构成变量和函数的名字。例如,下面是分别用骆驼式命名法和下划线法命名的同一个函数:

    printEmployeePaychecks();
    print_employee_paychecks();
    

    第一个函数名使用了驼峰命名法,函数名中的每一个逻辑断点都有一个大写字母来标记。第二个函数名使用了下划线法,函数名中的每一个逻辑断点都有一个下划线来标记。

    驼峰命名法近年来越来越流行了,在许多新的函数库和Microsoft Windows这样的环境中,它使用得当相多。另一方面,下划线法是C出现后开始流行起来的,在许多旧的程序和UNIX这样的环境中,它的使用非常普遍。

  2. 匈牙利命名法。广泛应用于象Microsoft Windows这样的环境中。Windows 编程中用到的变量(还包括宏)的命名规则为匈牙利命名法,这种命名技术是由一位能干的 Microsoft 程序员查尔斯-西蒙尼(Charles Simonyi) 提出的。

匈牙利命名法通过在变量名前面加上相应的小写字母的符号标识作为前缀,标识出变量的作用域、类型等。这些符号可以多个同时使用,顺序是先m_(成员变量)、再指针、再简单数据类型、再其它。这样做的好处在于能增加程序的可读性,便于对程序的理解和维护。

例如:m_lpszStr, 表示指向一个以0字符结尾的字符串的长指针成员变量。
匈牙利命名法关键是:标识符的名字以一个或者多个小写字母开头作为前缀;前缀之后的是首字母大写的一个单词或多个单词组合,该单词要指明变量的用途。
  1. 帕斯卡(pascal)命名法。与驼峰命名法类似,二者的区别在于:驼峰命名法是首字母小写,而帕斯卡命名法是首字母大写,如:

    DisplayInfo();
    string UserName;
    

    二者都是采用了帕斯卡命名法。

  2. 三种命名规则的小结:MyData就是一个帕斯卡命名的示例;myData是一个驼峰命名法,它第一个单词的第一个字母小写,后面的单词首字母大写,看起来像一个骆驼;iMyData是一个匈牙利命名法,它的小写的i说明了它的型态,后面的和帕斯卡命名相同,指示了该变量的用途。

命名的基本原则

  1. 标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解——尽量采用采用英文单词或全部中文全拼表示,若出现英文单词和中文混合定义时,使用连字符“_”将英文与中文割开。较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。例如:temp->tmp、flag->flg、statistic->stat、increment->inc、message->msg等缩写能够被大家基本认可。

  2. 命名中若使用特殊约定或缩写,则要有注释说明。应该在源文件的开始之处,对文件中所使用的缩写或约定,特别是特殊的缩写,进行必要的注释说明。

  3. 自己特有的命名风格,要自始至终保持一致,不可来回变化。个人的命名风格,在符合所在项目组或产品组的命名规则的前提下,才可使用。(即命名规则中没有规定到的地方才可有个人命名风格)。

  4. 对于变量命名,禁止取单个字符(如i 、j 、k... ),建议除了要有具体含义外,还能表明其变量类型、数据类型等,但i 、j 、k 作局部循环变量是允许的。变量,尤其是局部变量,如果用单个字符表示,很容易敲错(如i写成j),而编译时又检查不出来,有可能为了这个小小的错误而花费大量的查错时间。

  5. 除非必要,不要用数字或较奇怪的字符来定义标识符。

  6. 命名规范必须与所使用的系统风格保持一致,并在同一项目中统一。

  7. 在同一软件产品内,应规划好接口部分标识符(变量、结构、函数及常量)的命名,防止编译、链接时产生冲突。对接口部分的标识符应该有更严格限制,防止冲突。如可规定接口部分的变量与常量之前加上“模块”标识等。

  8. 用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。 下面是一些在软件中常用的反义词组:

    正义反义
    addremove
    beginend
    createdestroy
    insertdelete
    firstlast
    getrelease
    incrementdecrement
    putget
    adddelete
    lockunlock
    openclose
    minmax
    startstop
    nextprevious
    sourcetarget
    showhide
    sendreceive
    sourcedestination
    cutpaste
    updown

示例:

int  min_sum;
int  max_sum;
int  add_user( BYTE *user_name );
int  delete_user( BYTE *user_name );

(9)除了编译开关/ 头文件等特殊应用,应避免使用EXAMPLE_TEST 之类以下划线开始和结尾的定义。

变量名

  1. 变量的命名规则要求用匈牙利法则:开头字母用变量的类型,其余部分用变量的英文意思、英文的缩写、中文全拼或中文全拼的缩写,要求单词的第一个字母应大写

    即:变量名=变量类型+变量的英文意思(或英文缩写、中文全拼、中文全拼缩写)

    对非通用的变量,在定义时加入注释说明,变量定义尽量可能放在函数的开始处。

    变量类型及缩写:

    变量类型缩写示例
    boolbbFlg
    intiiCount
    short intnnStepCount
    long intllSum
    charccCount
    unsigned charbybyCount
    floatffAvarage
    doubleddDate
    unsigned int(WORD)wwCount
    unsigned long int(DWORD)dwdwBroad
    字符串ssFileName
    \0结尾的字符串szszFileName

其他

  • 全局变量:变量名=g_+变量类型+变量的英文意思(或缩写),如g_lFailCount

  • 静态变量:变量名=s_+变量类型+变量的英文意思(或缩写),如s_plPerv_Inst

  • 符号常量:常量全部大写,常量名用英文表达其意思。当需要多个单词表示是,单词与单词之间采用连字符-连接,如#define CM_FILE_NOT_FOUND CMMAKEHR(0X20B),其中CM表示类别;

  • const常量:在变量名命名的结果前加上c_,如const char* c_szFileName;

  • 指针类型:

    • 一级指针:p+变量类型前缀+命名,比如float*型指针命名为pfStat;
    • 二级指针:pp+变量类型前缀+命名,比如float**型指针命名为ppfStat;
  • 枚举类型:使用枚举变量或其缩写作为前缀,并且要求用大写,如:

    Enum cmEMDAYS{      // cm 代表小写的类别,如 int 的缩写 i;类型名全部大写`EMDAYS`
        EMDAYS_MONDAY;  // 每个枚举常量均以枚举名作为前缀`EMDAYS_`
        EMDAYS_TUESDAY;
    }
    
  • 结构体类型:以大写字母S开头,自定义的类型名大写,并加上前缀;结构体内部的变量命名与普通变量命名规则一致,如:

    Struct ScmNPoint{   // cm 为小写的类型名
        int nX;        // `n`为数据类型`short int`的缩写
        int nY;
    }
    
  • 联合体类型:U+变量类型+大写的英文类型名,如

    Union UcmLPoint{    
        LONG lX;        // `l`为数据类型`long int`的缩写
        LONG lY;
    }
    

函数

函数名命名规范

  1. 函数名应准确描述函数的功能:应尽量用英文(或英文缩写、中文全拼、中文全拼缩写)表达出函数完成的功能;
  2. 函数名遵循动宾结构的命名法则:函数名中动词在前,并在命名前加入函数的前缀;
  3. 函数名不得少于$8$ 个字符;
  4. 函数名中的单词首字母均大写;
  5. 如果函数为对象的方法,则函数名可只有动词(因为对象本身就是名词);
  6. 避免使用无意义或含义不清的动词为函数命名,比如process,handle等,因为这些动词并没有说明要具体做什么。
  7. 必须使用函数原型声明。具体包括:
    1. 引用外来函数时必须在函数声明的右侧著名函数来源,包括模块名及文件名;
    2. 引用内部函数时,只要注释其定义文件名,和调用者在同一文件中(简单程序)时不需要注释;
    3. 应确保每个函数声明中的参数的名称、类型和定义中的名称、类型一致;
LONG GetDeviceCount(……);
void print_record( unsigned int rec_ind ) ;
int  input_record( void ) ;
unsigned char get_current_color( void ) ;
int IsPrime(int iNatureNumber);         // 如果函数返回布尔值,则函数名采用 IS... 的形式

函数参数命名规范

  • 参数名称的命名参照变量命名规范;
  • 为了提高程序的运行效率,减少参数占用的堆栈,传递大结构的参数,一律采用指针或引用方式传递。
  • 为了便于其他程序员识别某个指针参数是入口参数还是出口参数,同时便于编译器检查错误,应该在入口参数前加入const标志。如:……cmCopyString(const CHAR * c_szSource, CHAR * szDest)

文件名

(包括动态库、组件、控件、工程文件等)的命名规范文件名的命名要求表达出文件的内容,要求文件名的长度不得少于5个字母,严禁使用象file1,myfile之类的文件名;

来源于WFApple