C++ 编码规范

目录

1、代码总体原则:

2、头文件

3、函数

4、标识符命名与定义

5、变量

6、宏、常量

7、表达式

8、注释

9、排版与格式

10、代码编辑编译


1、代码总体原则:

(1)清晰第一;

(2)简洁为美;

(3)选择合适的风格,与代码原有风格保持一致;

2、头文件

(1)头文件中适合放置接口的声明,不适合放置实现;

(2)头文件应当职责单一,切忌依赖复杂;

(3)禁止在头文件中定义变量;

(4)禁止在 extern "C" 中包含头文件:

    在extern "C"中包含头文件,会导致extern "C"嵌套,Visual Studio对extern "C"嵌套层次有限制,嵌套层次太多会编译错误。

    在extern "C"中包含头文件,可能会导致被包含头文件的原有意图遭到破坏。

(5)一个模块通常包含多个 .c 文件,建议放在同一个目录下,目录名即为模块名。为方便外部使用者,建议每一个模块提供一个 .h ,文件名为目录名;

(6)如果一个模块包含多个子模块,则建议每一个子模块提供一个对外的 .h,文件名为子模块名;

    降低接口使用者的编写难度;

(7)头文件不要使用非习惯用法的扩展名,如 .inc;

    目前很多产品中使用了.inc作为头文件扩展名,这不符合c语言的习惯用法。

(8)同一产品统一包含头文件排列方式;

    常见的包含头文件排列方式:功能块排序、文件名升序、稳定度排序(建议将不稳定的头文件放在前面,及早知道错误)。

3、函数

    函数设计的精髓:编写整洁函数,同时把代码有效组织起来。

    代码的有效组织包括:逻辑层组织和物理层组织两个方面。

    逻辑层:主要是把不同功能的函数通过某种联系组织起来,主要关注模块间的接口,也就是模块的架构。

    物理层:无论使用什么样的目录或者名字空间等,需要把函数用一种标准的方法组织起来。

    例如:设计良好的目录结构、函数名字、文件组织等,这样可以方便查找。

(1)一个函数仅完成一件功能;

(2)重复代码应该尽可能提炼成函数;(2次考虑,3次就要改)

(3)避免函数过长,新增函数不超过 50 行 (非空非注释行);

(4)避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层;

(5)可重入函数应避免使用共享变量;若需要使用,则应通过互斥手段(关中断、信号量)对其加以保护;

(6)对参数的合法性检查,由调用者负责还是由接口函数负责,应在项目组/模块内应统一规定。缺省由调用者负责;

(7)对函数的错误返回码要全面处理;

(8)设计高扇入,合理扇出(小于7)的函数;

    扇出是指一个函数直接调用(控制)其它函数的数目,而扇入是指有多少上级函数调用它。

    较良好的软件结构通常是顶层函数的扇出较高,中层函数的扇出较少,而底层函数则扇入到公共模块中。

(9)废弃代码(没有被调用的函数和变量) ) 要及时清除;

(10)函数不变参数使用const;

(11)函数应避免使用全局变量、静态局部变量和 I/O 操作,不可避免的地方应集中使用;

    带有内部存储器的函数的输出可能取决于内部存储器的状态,因为函数的输出是根据其输入和内部状态计算出来的。

    如果函数的内部状态改变了,那么相同的输入可能会产生不同的输出。

(12)检查函数所有非参数输入的有效性,如数据文件、公共变量等;

(13)函数的参数个数不超过5个

(14)除打印类函数外,不要使用可变长参函数;

(15)在源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加static关键字;

4、标识符命名与定义

(1)标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解;

(2)除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音

    argument 可缩写为 arg

    buffer 可缩写为 buff

    clock 可缩写为 clk

    command 可缩写为 cmd

    compare 可缩写为 cmp

    configuration 可缩写为 cfg

    device 可缩写为 dev

    error 可缩写为 err

    hexadecimal 可缩写为 hex

    increment 可缩写为 inc

    initialize 可缩写为 init

    maximum 可缩写为 max

    message 可缩写为 msg

    minimum 可缩写为 min

    parameter 可缩写为 para

    previous 可缩写为 prev

    register 可缩写为 reg

    semaphore 可缩写为 sem

    statistic 可缩写为 stat

    synchronize 可缩写为 sync

    temp 可缩写为 tmp

(3)产品/项目组内部应保持统一的命名风格;

(4)用正确的反义词组命名具有互斥意义的变量或相反动作的函数等;

    add/remove begin/end create/destroy

    insert/delete first/last get/release

    increment/decrement put/get add/delete

    lock/unlock open/close min/max

    old/new start/stop  next/previous

    source/target show/hide  send/receive

    source/destination copy/paste up/down

(5)尽量避免名字中出现数字编号,除非逻辑上的确需要编号;

(6)标识符前不应添加模块、项目、产品、部门的名称作为前缀;

(7)平台/ / 驱动等适配代码的标识符命名风格保持和平台;

(8)重构/修改部分代码时,应保持和原有代码的命名风格一致;

(9)文件命名统一采用小写字符;

(10)全局变量应增加“g_” 前缀,静态变量应增加“s_”;

(11)禁止使用单字节命名变量,但 允许 定义i 、j、k作为局部循环变量;

(12)不建议使用匈牙利命名法;

(13)使用名词或者形容词+名词方式命名变量;

(14)函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构;

(15)函数指针除了前缀,其他按照函数的命名规则命名;

(16)对于数值或者字符串等等常量的定义,建议采用全大写字母,单词之间加下划线“_”的方式命名(枚举同样建议使用此方式定义);

    #define PI_ROUNDED 3.14

(17)除了头文件或编译开关等特殊标识定义,宏定义不能使用下划线“_”开头和结尾;

5、变量

(1)一个变量只有一个功能,不能把一个变量用作多种用途;

(2)结构功能单一,不要设计面面俱到的数据结构;

(3)不用或者少用全局变量;

(4)防止局部变量与全局变量同名;

(5)通讯过程中使用的结构,必须注意字节序;

(6)严禁使用未经初始化的变量作为右值;

(7)构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的全局变量,防止多个不同模块或函数都可以修改、创建同一全局变量的现象;

    降低全局变量耦合度。

(8)使用面向接口编程思想,通过 API 访问数据:如果本模块的数据需要对外部模块开放 ,应提供接口函数来设置、获取,同时注意全局数据的访问互斥;

(9)明确全局变量的初始化顺序,避免跨模块的初始化依赖;

(10)尽量减少没有必要的数据类型默认转换与强制转换;

6、宏、常量

(1)用宏定义表达式时,要使用完备的括号;

    #define RECTANGLE_AREA(a, b) ((a) * (b))

(2)将宏所定义的多条表达式放在大括号中;

(3)使用宏时,不允许参数发生变化;    

    同时也建议即使函数调用,也不要在参数中做变量变化操作,

    因为可能引用的接口函数,在某个版本升级后,变成了一个兼容老版本所做的一个宏,结果可能不可预知。

(4)不允许直接使用魔鬼数字

(5)除非必要,应尽可能使用函数代替宏;

    宏对比函数,有一些明显的缺点:

        宏对比函数,有一些明显的缺点:

        宏展开可能会产生意想不到的副作用;

        以宏形式写的代码难以调试难以打断点,不利于定位问题;

        宏如果调用的很多,会造成代码空间的浪费,不如函数空间效率高。

(6)常量建议使用 const 定义代替宏:宏的名字不进入代码,排查问题难定位;

    const double ASPECT_RATIO = 1.653;

(7)宏定义中尽量不使用 return 、 goto 、 continue 、 break等改变程序流程的语句;

7、表达式

(1)表达式的值在标准所允许的任何运算次序下都应该是相同的

(2)函数调用不要作为另一个函数的参数使用,否则对于代码的调试、阅读都不利

(3)赋值语句不要写在 if 等语句中,或者作为函数的参数使用;

    作用函数参数来使用,参数的压栈顺序不同可能导致结果未知。

(4)用括号明确表达式的操作顺序,避免过分依赖默认优先级;

(5)赋值操作符不能使用在产生布尔值的表达式上;

8、注释

(1)优秀的代码可 以自我解释,不通过注释即可轻易读懂

(2)注释的内容要清楚、明了,含义准确,防止注释二义性;

(3)在代码的功能、意图层次上进行注释,即注释解释 代码难以直接表达的意图 , 而不是重复描述代码;

(4)修改代码时,维护代码周边的所有注释,以保证注释与代码的一致性,不再有用的注释要删除;

(5)文件头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者姓名、工号、内容、功能说明、与其它文件的关系、修改日志等,

    头文件的注释中还应有函数功能简要说明

(6)函数声明处注释描述函数功能、性能及用法,包括输入和输出参数、函数返回值、可重入的要求等;

    定义处详细描述函数功能和实现要点,如实现的简要步骤、实现的理由、 设计约束等

(7)全局变量要有较详细的注释,包括对其功能、取值范围以及存取时注意事项等的说明;

(8)注释应放在其代码上方相邻位置或右方,不可放在下面,如放于上方则需与其上面的代码用空行隔开,且与下方代码缩进相同;

(9)对于 switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,

    必须在该case语句处理完、下一个case语句前加上明确的注释

(10)避免在注释中使用缩写,除非是业界通用或子系统内标准化的缩写

(11)同一产品或项目组统一注释风格

(12)避免在一行代码或表达式的中间插入注释

(13)注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,

    除非能用非常流利准确的英文表达,对于有外籍员工的,由产品确定注释语言

    注释语言不统一,影响程序易读性和外观排版,出于对维护人员的考虑,建议使用中文。

(14)文件头、函数头、全局常量变量、类型定义的注释格式采用工具可识别的格式

9、排版与格式

(1)程序块采用缩进风格编写, 每级缩进为4个空格;

(2)相对独立的程序块之间、变量说明之后必须加空行;

(3)一条语句不能过长,如不能拆分需要分行写。一行到底多少字符换行比较合适,产品可以自行确定;

(4)多个短语句(包括赋值语句)不允许写在同一行内 ,即一行只写一条语句;

(5)if 、 for 、 do 、 while 、 case 、 switch 、 default 等语句独占一行;

(6)在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格 ; 

    进行非对等操作时,如果是关系密切的立即操作符(如-> > ),后不应加空格;

(7)注释符(包括/**/、//)与注释内容之间要用一个空格进行分隔;

(8)源程序中关系较为紧密的代码应尽可能相邻;

10、代码编辑编译

(1)使用编译器的最高告警级别,理解所有的告警,通过修改代码而不是降低告警级别来消除所有告警;

(2)在产品软件(项目组)中,要统一编译开关、静态检查选项以及相应告警清除策略;

(3)本地构建工具(如 PC-Lint)的配置应该和持续集成的一致;

    两者一致,避免经过本地构建的代码在持续集成上构建失败;

(4)使用版本控制(配置管理)系统,及时签入通过本地构建的代码,确保签入的代码不会影响构建成功;

    及时签入代码降低集成难度。

(5)要小心地使用编辑器提供的块拷贝功能编程;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值