C语言编程规范

代码命名规范

通用规范:

  • 类型名用大写,变量名和常量名用小写
  • 变量名前加变量类型,如u16count,ptext
  • 所有宏定义、枚举项、结构体成员、联合体成员一定要加注释,并使用块注释

具体规范:

  • 宏:

    • 采用大写下划线,如果宏定义的是函数可以采用小写
    • 为了更好地区分宏所属的模块,建议加模块前缀
  • 枚举

    • 枚举类型名使用大写,如若使用typedef定义枚举名,则枚举类型名后面加_E后缀
    • 枚举成员名使用大写
    • 枚举成员名最好添加模块前缀
  • 结构体、联合体

    • 类型名使用大写,如若使用typedef定义枚举名,则枚举类型名后面加_S后缀
    • 成员变量名使用小写,且需要相应注释
  • 全局变量:一律使用小写

    • 仅文件内部使用:添加s_um_前缀
    • 文件外部能访问:添加g_um_前缀
  • 函数:一律使用小写下划线

    • 仅供文件内部调用:可以不添加前缀
    • 允许文件外部调用:添加um前缀
    • 强调内部使用:添加__(双下划线)前缀
  • 局部变量:一律使用小写下划线

  • 基本类型:类型名使用大写

  • 编译器版本间的兼容:有内联需求的,应使用__inline而非直接inline

语法和语义

  1. 变量定义后一定要初始化

  2. 删除未使用变量,去除编译时警告

  3. 函数无返回值则返回类型为void,函数无参数则参数类型为void,对有返回值的函数一定要处理返回值

  4. 声明统一放头文件或源文件最前面

  5. debug版本中,函数传入的参数要使用assert进行检测,便于调试时排错

  6. 使用显示数据类型转换,避免编译器隐式转换

  7. 减少全局变量的使用

  8. 函数名和变量名不要同名,局部变量和全局变量不要同名

  9. 关于内存:

    • 指针变量一定要初始化,无指向对象时先初始化为NULL,防止使用了野指针
    • 动态分配内存要判断结果是否成功
    • malloc和free要配套使用
    • 释放内存后,要将指针指向NULL,防止野指针
  10. 常量

    • 对外公开的放在头文件中,不公开的放在定义文件的头部
    • 常量之间有密切联系时,应该在定义中显示出来,避免给出一些孤立的值
    • C++中有两种定义常量的方式:
      • const:有数据类型,编译器对其进行安全类型检查,可调试
      • define:无数据类型,编译器不对其进行安全类型检查,不可调试
    • 使用宏定义表达式时,要使用完备的括号
    • 宏定义有多条表达式,则表达式应该放在大括号中
    • 使用宏时,不允许参数发生变化(自增自减)
  11. const关键字

    • 使用const修饰函数参数时,只能修饰输入参数
    • C语言中,const修饰的是只读变量,C语言中定义常量的方法是宏define和枚举enum
  12. 变量:定义时一定要初始化,尽管全局变量和静态变量会有默认的初始值

  13. 避免使用bool参数,原因:

    • bool参数值无意义,true/false的含义非常模糊,在调用时很难知道参数传达的意思
    • bool参数值不利于扩充
  14. 关键字使用和语句使用规范

    • if语句

      • 使用if(NULL == p)代替if(p == NULL),避免写少了等号
      • 多个if语句判断时,将能预测到的最多情况放在第一个if语句中,从而提高效率
    • for语句

      • 不可在循环体内修改循环控制变量,防止for循环失去控制

      • 建议for语句的循环控制变量的取值采用“半开半闭区间”写法,采用“半开半闭区间”写法能够减少错误,例如防止数组越界

      • 在多重循环中,如果有可能,应当将最长的循环放在最内层,最短的循环放在最外层,以减少CPU跨切循环层的次数

      • 如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面(不是很懂)

        for (i=0; i<N; i++)
        {
        if (condition)
        DoSomething();
        else
        DoOtherthing();
        }
        //如果N非常大的话,应该采用右边的方法提高效率
        if (condition)
        {
        for (i=0; i<N; i++)
        DoSomething();
        }
        else
        {
        for (i=0; i<N; i++)
        DoOtherthing();
        }
        
      • 对于一次性的计算,不要放在for语句中

    • switch语句

      • 每个case语句的结尾不要忘记加break
      • 不要忘记缺省分支default,即使不需要也应添加default:break;
      • case后面的值只能是整形或字符型常量/常量表达式
      • case语句排列顺序:
        • 按字母或数字排序
        • 正常情况放前面,异常情况放后面
        • 按执行频率排列
      • case语句中不能使用continue
    • goto语句:少用、慎用

    • inline关键字:内联,空间换时间

      • 必须与函数定义体放在一起才能使函数内联
      • 以下情况不宜使用inline
        • 函数体代码较长
        • 函数体内有循环
    • volatile关键字:修饰被不同线程访问和修改的变量,即修饰易变变量,保证每次读取时都重新读取

    • extern关键字:调用其他模块的变量或函数,要在本模块中用extern进行外部声明

    • void关键字

      • 函数没有返回值或没有参数时,应声明为void类型
      • 函数参数为任意指针类型时,声明为void *

机器或平台相关