您当前的位置:首页业界 >  >> 
菊厂C语言编码规范?
来源:面包芯语      时间:2023-09-08 20:14:01

坚持下列措施可以避免内存泄漏:

规则6.3 禁止引用已经释放的内存空间。


(资料图片)

规则6.4 编程时,要防止差1错误。

说明:此类错误一般是由于把“<=”误写成“<”或“>=”误写成“>”等造成的,由此引起的后果,很多情况下是很严重的,所以编程时,一定要在这些地方小心。当编完程序后,应对这些操作符进行彻底检查。使用变量时要注意其边界值的情况。

建议6.1 函数中分配的内存,在函数退出之前要释放。

说明:有很多函数申请内存,,保存在数据结构中,要在申请处加上注释,说明在何处释放。

建议6.2 if语句尽量加上else分支,对没有else分支的语句要小心对待。

建议6.3 不要滥用goto语句。

说明:goto语句会破坏程序的结构性,所以除非确实需要,最好不使用goto语句。

建议6.4 时刻注意表达式是否会上溢、下溢。

七、 程序效率

原则7.1 在保证软件系统的正确性、简洁、可维护性、可靠性及可测性的前提下,提高代码效率。

原则7.2 通过对数据结构、程序算法的优化来提高效率。

建议7.1 将不变条件的计算移到循环体外。

建议7.2 对于多维大数组,避免来回跳跃式访问数组成员。

建议7.3 创建资源库,以减少分配对象的开销。

建议7.4 将多次被调用的 “小函数”改为inline函数或者宏实现。

八、 注释

原则8.1 优秀的代码可以自我解释,不通过注释即可轻易读懂。

说明:优秀的代码不写注释也可轻易读懂,注释无法把糟糕的代码变好,需要很多注释来解释的代码往往存在坏味道,需要重构。

原则8.2 注释的内容要清楚、明了,含义准确,防止注释二义性。

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

规则8.1 修改代码时,维护代码周边的所有注释,以保证注释与代码的一致性。不再有用的注释要删除。

规则8.2 文件头部应进行注释,注释必须列出:版权说明、版本号、生成日期、作者姓名、工号、内容、功能说明、与其它文件的关系、修改日志等,头文件的注释中还应有函数功能简要说明。

规则8.3 函数声明处注释描述函数功能、性能及用法,包括输入和输出参数、函数返回值、可重入的要求等;定义处详细描述函数功能和实现要点,如实现的简要步骤、实现的理由、设计约束等。

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

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

规则8.6 对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释。

规则8.7 避免在注释中使用缩写,除非是业界通用或子系统内标准化的缩写。

规则8.8 同一产品或项目组统一注释风格。

建议8.1 避免在一行代码或表达式的中间插入注释。

建议8.2 注释应考虑程序易读及外观排版的因素,使用的语言若是中、英兼有的,建议多使用中文,除非能用非常流利准确的英文表达。对于有外籍员工的,由产品确定注释语言。

建议8.3 文件头、函数头、全局常量变量、类型定义的注释格式采用工具可识别的格式。

说明:采用工具可识别的注释格式,例如doxygen格式,方便工具导出注释形成帮助文档。

九、 排版与格式

规则9.1 程序块采用缩进风格编写,每级缩进为4个空格。

说明:当前各种编辑器/IDE都支持TAB键自动转空格输入,需要打开相关功能并设置相关功能。编辑器/IDE如果有显示TAB的功能也应该打开,方便及时纠正输入错误。

规则9.2 相对独立的程序块之间、变量说明之后必须加空行。

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

换行时有如下建议:

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

规则9.5 if、for、do、while、case、switch、default等语句独占一行。

规则9.6 在两个以上的关键字、变量、常量进行对等操作时,它们之间的操作符之前、之后或者前后要加空格;进行非对等操作时,如果是关系密切的立即操作符(如->),后不应加空格。

建议9.1 注释符(包括„/‟„//‟„/‟)与注释内容之间要用一个空格进行分隔。

建议9.2 源程序中关系较为紧密的代码应尽可能相邻。

十、 表达式

规则10.1 表达式的值在标准所允许的任何运算次序下都应该是相同的。

建议10.1 函数调用不要作为另一个函数的参数使用,否则对于代码的调试、阅读都不利。

建议10.2 赋值语句不要写在if等语句中,或者作为函数的参数使用。

建议10.3 赋值操作符不能使用在产生布尔值的表达式上。

十一、 代码编辑、编译

规则11.1 使用编译器的最高告警级别,理解所有的告警,通过修改代码而不是降低告警级别来消除所有告警。

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

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

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

建议11.1 要小心地使用编辑器提供的块拷贝功能编程。

十二、 可测性

原则12.1 模块划分清晰,接口明确,耦合性小,有明确输入和输出,否则单元测试实施困难。

说明:单元测试实施依赖于:

规则12.1 在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调测开关及相应打印函数,并且要有详细的说明。

规则12.2 在同一项目组或产品组内,调测打印的日志要有统一的规定。

说明:统一的调测日志记录便于集成测试,具体包括:

规则12.3 使用断言记录内部假设。

规则12.4 不能用断言来检查运行时错误。

说明:断言是用来处理内部编程或设计是否符合假设;不能处理对于可能会发生的且必须处理的情况要写防错程序,而不是断言。如某模块收到其它模块或链路上的消息后,要对消息的合理性进行检查,此过程为正常的错误检查,不能用断言来实现。

建议12.1 为单元测试和系统故障注入测试准备好方法和通道。

十三、 安全性

原则13.1 对用户输入进行检查。

说明:不能假定用户输入都是合法的,因为难以保证不存在恶意用户,即使是合法用户也可能由于误用误操作而产生非法输入。用户输入通常需要经过检验以保证安全,特别是以下场景:

这些情况下如果不对用户数据做合法性验证,很可能导致DOS、内存越界、格式化字符串漏洞、命令注入、SQL注入、缓冲区溢出、数据破坏等问题。

可采取以下措施对用户输入检查:

规则13.1 确保所有字符串是以NULL结束。

说明: C语言中‟\0‟作为字符串的结束符,即NULL结束符。标准字符串处理函数(如strcpy()、 strlen())

依赖NULL结束符来确定字符串的长度。没有正确使用NULL结束字符串会导致缓冲区溢出和其它未定义的行为。

为了避免缓冲区溢出,常常会用相对安全的限制字符数量的字符串操作函数代替一些危险函数。如:

这些函数会截断超出指定限制的字符串,但是要注意它们并不能保证目标字符串总是以NULL结尾。如果源字符串的前n个字符中不存在NULL字符,目标字符串就不是以NULL结尾。

规则13.2 不要将边界不明确的字符串写到固定长度的数组中。

说明:边界不明确的字符串(如来自gets()、getenv()、scanf()的字符串),长度可能大于目标数组长度,直接拷贝到固定长度的数组中容易导致缓冲区溢出。

规则13.3 避免整数溢出。

说明:当一个整数被增加超过其最大值时会发生整数上溢,被减小小于其最小值时会发生整数下溢。带符号和无符号的数都有可能发生溢出。

规则13.4 避免符号错误。

说明:有时从带符号整型转换到无符号整型会发生符号错误,符号错误并不丢失数据,但数据失去了原来的含义。

带符号整型转换到无符号整型,最高位(high-order bit)会丧失其作为符号位的功能。如果该带符号整数的值非负,那么转换后值不变;如果该带符号整数的值为负,那么转换后的结果通常是一个非常大的正数。

规则13.5:避免截断错误。

说明:将一个较大整型转换为较小整型,并且该数的原值超出较小类型的表示范围,就会发生截断错误,原值的低位被保留而高位被丢弃。截断错误会引起数据丢失。使用截断后的变量进行内存操作,很可能会引发问题。

规则13.6:确保格式字符和参数匹配。

说明:使用格式化字符串应该小心,确保格式字符和参数之间的匹配,保留数量和数据类型。格式字符和参数之间的不匹配会导致未定义的行为。大多数情况下,不正确的格式化字符串会导致程序异常终止。

规则13.7 避免将用户输入作为格式化字符串的一部分或者全部。

说明:调用格式化I/O函数时,不要直接或者间接将用户输入作为格式化字符串的一部分或者全部。攻击者对一个格式化字符串拥有部分或完全控制,存在以下风险:进程崩溃、查看栈的内容、改写内存、甚至执行任意代码。

规则13.8 避免使用strlen()计算二进制数据的长度。

说明:strlen()函数用于计算字符串的长度,它返回字符串中第一个NULL结束符之前的字符的数量。因此用strlen()处理文件I/O函数读取的内容时要小心,因为这些内容可能是二进制也可能是文本。

规则13.9 使用int类型变量来接受字符I/O函数的返回值。

规则13.10 防止命令注入。

说明:C99函数system()通过调用一个系统定义的命令解析器(如UNIX的shell,Windows的CMD.exe)来执行一个指定的程序/命令。类似的还有POSIX的函数popen()。

十四、 单元测试

规则14.1 在编写代码的同时,或者编写代码前,编写单元测试用例验证软件设计/编码的正确。

建议14.1 单元测试关注单元的行为而不是实现,避免针对函数的测试。

说明:应该将被测单元看做一个被测的整体,根据实际资源、进度和质量风险,权衡代码覆盖、打桩工作量、补充测试用例的难度、被测对象的稳定程度等,一般情况下建议关注模块/组件的测试,尽量避免针对函数的测试。尽管有时候单个用例只能专注于对某个具体函数的测试,但我们关注的应该是函数的行为而不是其具体实现细节。

十五、 可移植性

规则15.1 不能定义、重定义或取消定义标准库/平台中保留的标识符、宏和函数。

建议15.1 不使用与硬件或操作系统关系很大的语句,而使用建议的标准语句,以提高软件的可移植性和可重用性。

建议15.2 除非为了满足特殊需求,避免使用嵌入式汇编。

说明:程序中嵌入式汇编,一般都对可移植性有较大的影响。

本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

往期推荐

《嵌入式Linux驱动大全》

标签:

X 关闭

X 关闭

Copyright ©  2015-2022 北冰洋经济网版权所有  备案号:沪ICP备2020036824号-3   联系邮箱:562 66 29@qq.com