欢迎光临散文网 会员登陆 & 注册

如何写出好的代码(一) - 编程规范

2020-10-12 21:52 作者:奥大梨呀  | 我要投稿

    怎么写出好的代码,这涉及到很多方面。本文主要以编程规范和程序可移植性这两方面来说明。因为篇幅的原因,此次先介绍编程规范方面。

    相信很多朋友和笔者一样,在刚入门编程不久时,写的代码都是非常难看和移植的,尽管它可以运行。然而当你现在去看过去自己写的代码时,是不是觉得想一巴掌送给当时的自己:“你这写的是啥玩意?”。如果你没有这样的想法的话,说明朋友你在程序结构这方面不是很重视,又或者是相对来说进步不大。下面分享一些我学习到的经验,因我是做嵌入式开发常用C语言,因此就以C语言进行说明。

    那么首先我们先说说编程规范,这一点已经逐渐成为了程序员们的共识,网络上可以找到许多规范要求。这里我总结一些比较重要的。

    1.标识符的命名。命名需要让人“一看就知道什么作用”。比如一个接收缓冲区指针:rxbuff。函数宏定义等也是这样的要求。当然,不同的平台对标识符的命令略有差异,在linux提倡以下划线隔开单词的变量命名方式。而在QT5中,则是提倡第一个单词小写,第二个单词首字母大写的变量命名方式,如下图所示。

不同平台的标识符命名

    2.每个模块或者功能都分别使用一个C源文件和H头文件,不要全都挤在一个文件中。

头文件一般放函数声明,类型声明(如struct)和宏定义。而源文件则是变量和函数的定义。

    3.利用好关键字static,将不需要对外开发的函数变量等限定作用域在某个文件中。全局变量一般都定义为static类型,其他文件需要操作时,使用一个函数对外提供接口。这点在后面程序可移植性时会再提到。

    4.对于双目运算符来说,其两边各加上一个空格,而单目运算符则不需要,对于逗号是在其后方加上一个空格。在不同作用的代码段之间空行,不至于让代码都挤在一起。

加空格与空行

5.在定义变量时对变量进行初始化,尤其是指针,一般初始化为NULL,避免“野指针”的出现。

变量初始化

6.要在适当的地方使用TAB或空格缩进,一定要统一,要么都使用空格,要么都使用TAB,因为不同的开发环境,对于TAB定义的长度都是不同的,如果空格和TAB混用,那么在其他开发环境打开时,可能就乱糟糟的了。还有大括号最好在成对出现在同一列,像这样

缩进与对齐1

当然有些地方也提倡这样的写法:

缩进与对齐2

这种把第一个大括号紧跟在后的写法我个人其实不是很喜欢,每两个大括号的配对看起来不是很清晰。因此我更多的是采用第一种写法,当然这要看每个人的喜好了,不论是哪一种,只要不是像下面这样乱糟糟的就行了:

错误范例

这要是代码量一大,鬼知道哪个括号配哪个。

    7.学会合理地写注释。这一点非常重要,大家都调侃说“程序员讨厌没有注释的代码,也讨厌写注释”。前半句我认为很合理,而后半句应该是这样“讨厌写不必要的注释”。写注释的目的大多是为了方便自己以后能快速读懂自己写的代码,仅有少部分是让后来的人看的。不必要写的注释意思是有些语句一看就懂没必要写注释,比如:GPIOB->BSRR = 1 << 5;我相信学过STM32的肯定看一眼就知道这是什么意思。相对而言,对某些变量的作用,其位操作,计算等,这些就比较需要注释了。否则后面再看的时候,我想一时半会应该是不明白自己当时写这些是什么意思吧。拿我之前写的DMA数码管驱动来说吧,下图:

驱动 - 初始化显存

这段代码大概是4个月前写的,现在打开,凭着这段注释,我还能在30秒内理清我当时所想的思路。但要是拿掉注释,估计得花不少时间来解读这段代码了。

    8.多行的宏定义使用do-while(0)进行封装,而不是使用大括号{}。见下图(图中的 ’\’ 是用来续下一行的,且whle(0)后不加分号):

多行宏定义封装

使用do-while(0)的好处是符合函数调用后加上分号的习惯,也能避免一些错误。详情见下图:

宏定义调用

这种情况下,如果宏定义使用do-while(0)的形式不会出现任何问题,但如果采用大括号{}的形式,代码在预编译阶段时会被替换成这样:

宏定义替换

很明显问题就出来了,下面的else因为被一个分号隔开,无法与if配对,编译报错。若去掉分号,又不符合书写习惯,想想一个像函数调用的语句后面没有分号,看起来是不是很奇怪?

    9.正确书写main函数的格式。main函数的写法网络上大概有下面这么几种:

main函数写法

目前而言,标准的写法只有标注释的这3种,前面3种不标准,尽管有些地方不需要写标准的main函数,比如单片机裸机编程,但为了严格和习惯,还是按照标准来写比较好。

标准写法1适用于不需要向程序传递参数的情况。而写法2和3是等价的,argc表示参数的个数,argv表示参数阵列。

而对于最后一种,多了一个参数envp,是程序内部用来获取系统变量的,但通常都使用getenv()函数来代替之获取系统变量,因此不使用这种格式。

    以上就是我目前能想到的一些比较重要的编程规范了。如果有什么遗漏或者错误,还请批评指正。

    另外,Up平常主要是利用课余时间做各种单片机项目练习,兼学习Linux知识。后面可能会做一些项目的视频,最近应该是随缘更新专栏了吧。这在里也感谢各位朋友的关注。


如何写出好的代码(一) - 编程规范的评论 (共 条)

分享到微博请遵守国家法律