C/C++ 编程规范总结

目录

前言

一、编程规范的作用

二、规范的三种形式

三、规范的内容

1. 基本原则

原则1-1

原则1-2

原则1-3

原则1-4

原则1-5

原则1-6

原则1-7

2. 布局

规则2-1-1

规则2-1-2

规则2-1-3

规则2-1-4

规则2-1-5

规则2-1-6

规则2-2-1

规则2-2-2

规则2-2-3

建议2-3-1

规则2-4-1

规则2-4-2

规则2-4-3

规则2-4-4

规则2-4-2

规则2-4-6

规则2-5-1

3. 注释

规则3-1

规则3-2

规则3-3

​编辑

规则3-4

4. 命名规则

规则4-1

规则4-2

规则4-3

规则4-4

规则4-5

规则4-6

规则4-7

规则4-8

规则4-9

规则4-10

规则4-11

建议4-12

建议4-13

5. 变量、常量与类型

规则5-1

规则5-2

建议5-3

6. 表达式与语句

规则6-1

规则6-2

规则6-3

规则6-4

规则6-5        

​编辑

规则6-6

​编辑

规则6-7

规则6-8

规则6-9

建议6-10

7. 函数与过程

规则7-1

规则7-2

规则7-3

规则7-4

规则7-5

建议7-6

建议7-7

建议7-8

建议7-9

8. 可靠性

规则8-1

规则8-2

规则8-3

规则8-4

规则8-5

规则8-6

规则8-7

规则8-8

建议8-9

9. 可测试性

规则9-1

规则9-2

规则9-3

10.断言与错误外理

规则10-1

规则10-2

规则10-3


前言

编码规范是成为一个优质程序员的重要一课,它是编程的样式的模板。

为了跟大佬们一样写出简洁、可维护、可靠、可测试、高效、可移植的代码,我参考网上的资料做了一个归类。

一、编程规范的作用

1.提高源程序的可读性和可维护性

2.降低错误的机会

3.提高源代码可重用性和质量

二、规范的三种形式

1.原则:编程时应该坚持的指导思想

2.规则:编程时必须遵守的约定

3.建议: 编程时必须加以考虑的约定

三、规范的内容

1. 基本原则

原则1-1

首先是为人编写程序,其次才是计算机。
说明:这是软件开发的基本要点,软件的生命周期贯穿产品的开发、测试、生产、用户使用、版本升级和后期维护等长期过程,只有易读、易维护的软件代码才具有生命力。

原则1-2

保持代码的简明清晰,避免过分的编程技巧。
简单是最美。保持代码的简单化是软件工程化的基本要求。不要过分追求技巧,否则会降低程序的可读性。

原则1-3

所有的代码尽量遵循ANSI C标准
所有的代码尽可能遵循ANSI C标准,尽可能不使用ANSI C未定义的或编译器扩展的功能。

原则1-4

编程时首先达到正确性,其次考虑效率。
编程首先考虑的是满足正确性、健壮性、可维护性、可移植性等质量因素,最后才考虑程序的效率和资源占用。

原则1-5

避免或少用全局变量
过多地使用全局变量,会导致模块间的紧耦合违反模块化的要求

原则1-6

尽量遥免使用GOTO语句

原则1-7

尽可能复用、修正老的代码。
尽量选择可借用的代码,对其修改优化以达到自身要求。

2. 布局

规则2-1-1

遵循统一的布局顺序来书写头文件#ifmndef 文件名 H(全大写)
#defie
文件名 H
其它条件编译选项
#include(依次为标准库头文件、非标准库头文件)常量定义
全局宏
全局数据类型
类定义
模板 (template)(包括C++中的类模板和函数模板) 全局函数原型
#endif

规则2-1-2

遵循统一的布局顺序来书写实现文件
文件头注释
#include(依次为标准库头文件、非标准库头文件)常量定义
文件内部使用的宏
文件内部使用的数据类型
全局变量
本地变量(即静态全局变量)
局部函数原型
类的实现全局函数局部函数

规则2-1-3

使用注释块分离上面定义的节

规则2-1-4

头文件必须要避免重复包含

规则2-1-5

包含标准库头文件用尖括号 < >

包含非标准库头文件用双引号 " "

规则2-1-6

遵循统一的顺序书写类的定义及实现

类的定义(在定义文件中) 按如下顺序书写:

  • 公有属性,公有函数
  • 保护属性,保护函数
  • 私有属性,私有函数

类的实现(在实现文件中) 按如下顺序书写:

  • 构造函数,析构函数
  • 公有函数
  • 保护函数
  • 私有函数

规则2-2-1

程序中一行的代码和注释不能超过80列
包括空格在内不超过80列

规则2-2-2

if、 else、 else if、 for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{ }

规则2-2-3

结构型的数组、多维的数组如果在定义时初始化,按照数组的矩阵结构分行书写。

建议2-3-1

在switch语句中,每一个case分支和default要用{ }括起来,{ }中的内容需要缩进。

规则2-4-1

不同逻辑程序块之间要使用空行分隔

规则2-4-2

多元运算符和它们的操作数之间至少需要一个空格。

规则2-4-3

关键字之后要留空格

if、for、while等关键字之后应留一个空格再跟左括号 ’(’,以突出关键字

另外 sizeof 是关键字,strlen 是函数

规则2-4-4

函数名之后不要留空格

函数名后紧跟左括号 ’(’,以与关键字区别

规则2-4-2

不是行结束符号时其后要留空格

规则2-4-6

注释符与注释内容之间要用一个空格进行分隔

规则2-5-1

函数声明时,类型与名称不允许分行书写

3. 注释

规则3-1

文件头部必须进行注释,包括:.h文件、.c文件、.cpp文件、.inc文件、.def文件、编译说明文件.cfg等。
注释必须列出:版权信息、文件标识、内容摘要、版本号、作者、完成日期、修改信息等

规则3-2

函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、访问和修改的表、修改信息等。
说明:注释必须列出:函数名称、功能描述、输入参数、输出参数、返回值、修改信息等

规则3-3

包含在中代码块的结束处应加注释,便于阅读。

特别是多分支、多重嵌套的条件语句或循环语句。

规则3-4

注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释) 相邻位置不可放在下面,如放于上方则需与其上面的代码用空行隔开


4. 命名规则

规则4-1

标识符要采用英文单词或其组合,便于记忆和阅读,切总使用汉语拼音来命名。

标识符应当直观且可以拼读,可望文知义,避免使人产生误解。程序中的英文单词一般不要太复杂,用词应当准确。

规则4-2

标识符的命名应当符合“min-lengt && max-information”原则
较短的单词可通过去掉“元音”形成缩写,较长的单词可取单词的头几个字母形成缩写,一些单词有大家公认的缩写,常用单词的缩写必须统一。协议中的单词的缩写与协议保持一致对于某个系统使用的专用缩写应该在某处做统一说明。

例如:

  • temp 可缩写为 tmp ;
  • flag 可缩写为 flg ;
  • statistic 可缩写为 stat ;
  • increment 可缩写为 inc ;
  • message 可缩写为 msg ;

规则4-3

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

  • add / remove;
  • begin / end;
  • create / destroy;
  • insert / delete;
  • first / last;
  • get / release;
  • increment / decrementputget;
  • lock / unlock ;
  • open / close ;
  • min / max;
  • old / new;
  • start / stop;
  • source / target ;
  • next / previous;
  • show / hide;
  • send / receive ;
  • source / destination;
  • cut / paste;
  • up / down;

规则4-4

宏、常量名都要使用大写字母,用下划线 '_' 分割单词。

预编译宏定义使用下划线 '_' 开始。

例如:

DISP_BUF_SIZE、MIN_VALUE、MAX_VALUE 

规则4-5

变量名长度应小于31个字符,以保持与ANSI C标准一致。

不得取单个字符(如i、j、k等)作为变量名,但是局部循环变量除外。

规则4-6

程序中局部变量不要与全局变量重名
尽管局部变量和全局变量的作用域不同而不会发生语法错误,但容易使人误解。

规则4-7

使用一致的前缀来区分变量的作用域
变量活动范围前缀规范如下:

规则4-8

使用一致的小写类型指示符作为前缀来区分变量的类型。

规则4-9

完整的变量名应由前缀+变量名主体组成,变量名的主体应当使用“名词”或者“形容词 + 名词”,且首字母必须大写。

例如:

  • float g fValue; // 类型为浮点数的全局变量
  • char *pcOldChar; // 类型为字符指针的局部变量char

规则4-10

  • 结构名、联合名、枚举名由前缀T_开头。
  • 事件名由前缀EV 开头

规则4-11

类名采用大小写结合的方法。在构成类名的单词之间不用下划线,类名在开头加上C,类的成员变量统一在前面加m_前缀

建议4-12

尽量避免名字中出现数字编号,如Value1、Value2等,除非逻辑上的确需要编号

建议4-13

标识符前最好不加项目、产品、部门的标识
这样做的目的是为了代码的可重用性


5. 变量、常量与类型

规则5-1

宏定义中如果包含表达式或变量,表达式和变量必须用小括号括起来。
宏定义中,对表达式和变量使用括号,可以避免可能发生的计算错误

正例:
#define HANDLE(A,B) (( A ) / ( B ))

反例:
#define HANDLE(A,B)  (A / B)

规则5-2

使用宏定义多行语句时,必须使用把这些语句括起来。
在宏定义中,对多行语句使用大括号,可以避免可能发生的错误。

建议5-3

结构中元素的个数应适中。

若结构中元素个数过多可考虑依据某种原则把元素组成不同的子结构,以减少原结构中元素的个数


6. 表达式与语句

规则6-1

一条语句只完成一个功能

规则6-2

在表达式中使用括号,使表达式的运算顺序更清晰。
由于将运算符的优先级与结合律熟记是比较困难的,为了防止产生歧义并提高可读性,即使不加括号时运算顺序不会改变,也应当用括号确定表达式的操作顺序。

规则6-3

避免表达式中的附加功能,不要编写太复杂的复合表达式。

规则6-4

不可将布尔变量和逻辑表达式直接与TRUEFALSE或者1、0进行比较。TURE和FALSE的定义值是和语言环境相关的,且可能会被重定义的

规则6-5        

在条件判断语句中,当整型变量与0比较时,不可模仿布尔变量的风格,应当将整型变量用“==”或“!=”直接与0比较。

规则6-6

不可将浮点变量用“==”或“!=”上任何数字比较

规则6-7

应当将指针变量用“==”或“!=”与NULL比较

规则6-8

在switch语句中,每一个case分支必须使用break结尾,最后一个分支必须是default分支。

规则6-9

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

建议6-10

循环嵌套次数不大于3次


7. 函数与过程

规则7-1

如果函数没有参数,则用void填充

规则7-2

如果参数是指针,且仅作输入用,则应在类型前加const。
防止该指针在函数体内被意外修改

例如:

int GetStrLen(const char *pcString):

规则7-3

不要省略返回值的类型,如果函数没有返回值,那么应声明为void类型

  • C语言中,凡不加类型说明的函数,一律自动按整型处理。如果不注明类型,容易被误解为void类型,产生不必要的麻烦
  • C++语言有很严格的类型安全检查,不允许上述情况发生。由于C++程序可以调用C函数,为了避免混乱,规定任何C/ C++函数都必须有类型。

规则7-4

对于有返回值的函数,每一个分支都必须有返回值。
为了保证对被调用函数返回值的判断,有返回值的函数中的每一个退出点都需要有返回值。

规则7-5

防止将函数的参数作为工作变量
将函数的参数作为工作变量,有可能错误地改变参数内容,所以很危险。对必须改变的参数最好先用局部变量代之,最后再将该局部变量的内容赋给该参数。

建议7-6

如果返回值表示函数运行是否正常规定0为正常退出,不同非0值标识不同异常退出。避免使用TRUE或FALSE作为返回值

建议7-7

函数体的规模不能太大,尽量控制在200行代码之内

建议7-8

减少函数本身或函数间的递归调用
递归调用特别是函数间的递归调用 (如A->B->C->A),影响程序的可理解性,递归调用一般都占用较多的系统资源(如栈空间) ;递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。
对于前台软件为了系统的稳定性和可靠性,往往规定了进程的堆栈大小。如果采用了递归算法,收敛的条件又往往难以确定,很容易使得进程的堆栈溢出,破坏系统的正常运行:另外,由于无法确定递归的次数,降低了系统的稳定性和可靠性。

建议7-9

设计高扇入、合理扇出的函数
扇出是指一个函数直接调用(控制) 其它函数的数目,而扇入是指有多少上级函数调用它。
扇出过大,表明函数过分复杂,需要控制和协调过多的下级函数:而扇出过小,如总是1,表明函数的调用层次可能过多,这样不利于程序阅读和函数结构的分析,并且程序运行时会对系统资源如堆栈空间等造成压力。函数较合理的扇出(调度函数除外) 通常是3-5。扇出太大,一般是由于缺乏中间层次,可适当增加中间层次的函数。扇出太小,可把下级函数进步分解成多个函数,或合并到上级函数中。当然分解或合并函数时,不能改变要实现的功能,也不能违背函数间的独立性。

扇入越大,表明使用此函数的上级函数越多,这样的函数使用效率高,但不能违背函数间的独立性而单纯地追求高扇入。公共模块中的函数及底层函数应该有较高的扇入。


8. 可靠性

规则8-1

在程序编制之前,必须了解编译系统的内存分配方式,特别是编译系统对不同类型的变量的内存分配规则,如局部变量在何处分配、静态变量在何处分配等。

规则8-2

防止内存操作越界
内存操作主要是指对数组、指针、内存地址等的操作,内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细。

规则8-3

必须对动态申请的内存做有效性检查,并进行初始化;动态内存的释放必须和分配成对以防止内存泄漏,释放后内存指针置为NULL。

  • 对嵌入式系统,通常内存是有限的,内存的申请可能会失败,如果不检查就对该指针进行操作,可能出现异常,而且这种异常不是每次都出现比较难定位。
  • 指针释放后,该指针可能还是指向原有的内存块,可能不是,变成个野指针,一般用户不会对它再操作,但用户失误情况下对它的操作可能导致程序崩溃。

规则8-4

不使用realloc()。
调用realloc对一个内存块进行扩展,导致原来的内容发生了存储位置的变化, realloc函数既要调用free,又要调用malloc。执行时究竟调用哪个函数,取决于是要缩小还是扩大相应内存块的大小

规则8-5

变量在使用前应初始化,防止未经初始化的变量被引用。
不同的编译系统,定义的变量在初始化前其值是不确定的。有些系统会初始化为0,而有些不是

规则8-6

指针类型变量必须初始化为NULL

规则8-7

指针不要进行复杂的逻辑或算术操作。
指针加一的偏移,通常由指针的类型确定,如果通过复杂的逻辑或算术操作,则指针的位置就很难确定

规则8-8

如果指针类型明确不会改变,应该强制为const类型的指针,以加强编译器的检查
可以防止不必要的类型转换错误。

建议8-9

C++程序中,分配内存使用new和delete,而不使用malloc和free。
new和delete操作由编译器决定具体分配和释放内存的大小,相对于malloc和firee更为高级


9. 可测试性

规则9-1

在同一项目组或产品组内,为准备集成测试和系统联调,要有一套统一的调测开关及相应信息输出函数,并且要有详细的说明统一的调试接口和输出函数由模块设计和测试人员根据项目特性统一制订,由项目系统人员统一纳入系统设计中

规则9-2

在同一个项目组或产品组内,调测打印出的信息串要有统一的格式。信息串中应当包含所在的模块名(或源文件名) 及行号等信息。

规则9-3

在编写代码之前,应预先设计好程序调试与测试的方法和手段,并设计好各种调测开关及相应测试代码(如打印函数等)
程序的调试与测试是软件生存周期中非常重要的一个阶段,如何对软件进行较全面、高效率的测试并尽可能地找出软件中的错误就成为非常关键的问题。因此在编写源代码之前,除了要有一套比较完善的测试计划外,还应设计出一系列测试代码作为手段,为单元测试、集成测试及系统联调提供方便

10.断言与错误外理

规则10-1

整个软件系统应该采用统一的断言。如果系统不提供断言,则应该自己构造一个统一的断言供编程时使用。

规则10-2

指向指针的指针及更多级的指针必须逐级检查

规则10-3

正式软件产品中应把断言及其它调测代码去掉 (即把有关的调测开关关掉 ) ,加快软件运行速度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/234651.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

掌握iText:轻松处理PDF文档-基础篇

关于iText iText是一个强大的PDF处理库&#xff0c;可以用于创建、读取和操作PDF文件。它支持PDF表单、加密和签署等操作&#xff0c;同时支持多种字体和编码。maven的中央仓库中的最新版本是5.X&#xff0c;且iText5不是完全免费的&#xff0c;但是基础能力是免费使用的&…

pWnOS v2.0

该靶机绑定了静态IP地址 10.10.10.100&#xff0c;所以这里需要修改我们的网络配置&#xff01;整个网段修改为10.10.10.0/24 信息收集 主机存活探测 arp-scan -l 端口信息探测 nmap -sT --min-rate 10000 -p- 10.10.10.100 &#xff08;只开放了22 80端口&#xff09; 服务…

2023-12-10 LeetCode每日一题(爬楼梯)

2023-12-10每日一题 一、题目编号 70. 爬楼梯二、题目链接 点击跳转到题目位置 三、题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 示例 2&#xff1a; 提…

【Python】手把手教你用tkinter设计图书管理登录UI界面(三)

上一篇&#xff1a;【Python】手把手教你用tkinter设计图书管理登录UI界面&#xff08;二&#xff09;-CSDN博客 下一篇&#xff1a; 紧接上一篇文章&#xff0c;继续完善项目功能&#xff1a;用户登录。由于老王的注册部分有亿点点复杂&#xff0c;还没完成&#xff0c;但是…

期末速成数据库极简版【分支循环函数】(4)

目录 全局变量&局部变量 局部变量定义declare 局部变量赋值select 局部变量赋值select 【1】分支结构IF 【2】分支结构CASE 简单CASE语句 搜索CASE语句 【3】循环结构While 【4】系统函数 常用字符串函数 时间函数 【5】自定义函数—标量函数 函数创建 函…

oops-framework框架 之 Excel转Json

引擎&#xff1a; CocosCreator 3.8.0 环境&#xff1a; Mac Gitee: oops-plugin-excel-to-json 注&#xff1a; 作者dgflash的oops-framework框架QQ群&#xff1a; 628575875 配置 作者dgflash在oops-framework的框架中&#xff0c;提供了关于Excel数据表转换为Json和TypeSc…

typora中显示除号的问题

问题 在latex中“除号&#xff08; \div &#xff09;” 通常用 \div。但在typora中写数学公式时&#xff0c;却发现 “除号” 如果使用 \div 并没有显示为 “ \div ”&#xff0c;而是 “ ∇ ⋅ \nabla \cdot ∇⋅ ”。 原因 typora中&#xff0c;\div 显示为 ∇ ⋅ \…

Html转PDF,前端JS实现Html页面导出PDF(html2canvas+jspdf)

Html转PDF&#xff0c;前端JS实现Html页面导出PDF&#xff08;html2canvasjspdf&#xff09; 文章目录 Html转PDF&#xff0c;前端JS实现Html页面导出PDF&#xff08;html2canvasjspdf&#xff09;一、背景介绍二、疑问三、所使用技术html2canvasjspdf 四、展示开始1、效果展示…

Java第21章网络通信

网络程序设计基础 网络程序设计编写的是与其他计算机进行通信的程序。Java 已经将网络程序所需要的元素封 装成不同的类&#xff0c;用户只要创建这些类的对象&#xff0c;使用相应的方法&#xff0c;即使不具备有关的网络支持&#xff0c;也可 以编写出高质量的网络…

pyinstaller 常用命令参数

PyInstaller是一个用于将Python程序打包成独立的可执行文件的工具。它可以将Python代码和所有依赖的库、资源文件等打包成一个单独的可执行文件&#xff0c;方便在不安装Python解释器的环境中运行。PyInstaller提供了许多参数&#xff0c;用于配置打包过程和生成的可执行文件的…

NSS [NSSCTF 2022 Spring Recruit]babyphp

NSS [NSSCTF 2022 Spring Recruit]babyphp 考点&#xff1a;PHP特性 开局源码直接裸奔 <?php highlight_file(__FILE__); include_once(flag.php);if(isset($_POST[a])&&!preg_match(/[0-9]/,$_POST[a])&&intval($_POST[a])){if(isset($_POST[b1])&&…

java--Date、SimpleDateFormat时间类,JDK8之前的

1.Date 代表的是日期和时间 2.SimpleDateFormat 代表简单日期格式化&#xff0c;可以用来把日期对象、时间毫秒值格式化成我们想要的形式。 3.时间格式常见符号 4.SimpleDateFormat解析字符串时间成为日期对象

Redis之IO多路复用模型

Redis之IO多路复用模型 多路复用要解决的问题 解决同步阻塞IO模型下大量线程创建导致资源的浪费问题 同步阻塞IO模式的特点就是用一个进程来处理一个网络连接(一个用户请求)&#xff0c;比如一段典型的示例代码如下。 直接调用 recv 函数从一个 socket 上读取数据。 int main…

语义分割 简介及数据集简介

参考文章 MS COCO数据集介绍以及pycocotools简单使用-CSDN博客

Linux7安装tomcat9.0.83教程

1.下载tomcat.tar.gz包 地址&#xff1a;Apache Tomcat - Apache Tomcat 9 Software Downloads 2.将包上传到linux服并解压 cd /home/local # 跳转到上传包的目录 tar -zxvf apache-tomcat-9.0.83.tar.gz # 解压包 mv apache-tomcat-9.0.83 tomcat # 重命名目录为tomcat cp …

【PUSDN】SpringBoot的jar进行解压后,替换其中的文件重新生成新的jar-SW

当你解压Spring Boot的JAR文件时&#xff0c;实际上是在打开一个压缩文件&#xff0c;类似于ZIP。你可以按照以下步骤进行替换文件并重新生成新的JAR&#xff1a; 解压原始的JAR文件&#xff1a; 使用任何ZIP工具&#xff08;如WinRAR、7-Zip或命令行工具&#xff09;&#xf…

详解异常 ! !(对异常有一个全面的认识)

【本章目标】 1. 异常概念与体系结构 2. 异常的处理方式 3. 异常的处理流程 4. 自定义异常类 1. 异常的概念与体系结构 1.1 异常的概念 在生活中&#xff0c;一个人表情痛苦&#xff0c;出于关心&#xff0c;可能会问&#xff1a;你是不是生病了&#xff0c;需要我陪你去看医…

在线测试http接口,为您解析最佳测试方法

您是否正在寻找一种方便、高效且可靠的方法来测试您的http接口&#xff1f;在这篇文章中&#xff0c;我们将为您介绍在线测试http接口的最佳方法&#xff0c;帮助您确保您的接口在各种情况下都能正常运行。 什么是http接口&#xff1f; 在开始介绍如何测试http接口之前&#x…

AG1KLPQ48 User Manual

1.&#xff09;软件安装&#xff1a; 解压缩或执行安装文件&#xff0c;安装 Supra 软件。执行文件为 bin 目录中的 Supra.exe。 运行 Supra&#xff0c;选择菜单 File -> Import license&#xff0c;选择 license 文件并导入 License。 2.&#xff09;新建项目&#xff1a;…

掌握iText:轻松处理PDF文档-进阶篇

简体中文写入 iText本身对简体中文的支持有限&#xff0c;但可以通过引入额外的字体包来增强其对简体中文的支持。例如&#xff0c;可以使用iTextAsian.jar这个亚洲字体包&#xff0c;它包含了几种简单的亚洲字体&#xff0c;其中包括简体中文字体。只需要将iTextAsian.jar放到…