我的C语言编程风格
前几天看别人的代码,真是的看的头昏脑涨,基本没有注释、乱起的变量名字,还要费尽心思去解读作者的意思。突然感觉高效的程序注释说明和良好的编程风格是多么的重要。
为了不让别人在看到我的代码时在背后骂我,也为了更高效持久的开发,我想也应该是时候特别规定一下自己的编程风格了。
1、文件/文件夹命名
文件命名要精确,文件名要准确反映文件内容。
文件命名一律使用小写字母,如keyboard.c。
如有缩写单词,则必须大写,如flash_LED.c、UART.c。其中LED是Light-Emitting Diode(发光二极管)的缩写,UART是Universal Asynchronous Receiver/Transmitter(通用异步收发器,也就是串口)的缩写。对于有约定俗成缩写的单词,就使用缩写词汇。
文件名应使用名词,而不应该使用动词。如果文件内容是数据采集,应该命名为data_collection.c而非data_collect.c。
2、标识符命名
C语言中,可以定义各种标识符作为变量名、数组名、函数名、标号及用户定义对象的名称。ANSI C规定标识符必须由字母和下划线开始,随后可以出现字母、下划线和数字。
1)变量命名
变量命名一律小写,缩写词汇用大写,且全部使用名词,可以使用形容词修饰,用“_”表从属关系。因为变量名作为一个变量的名字,就应该是一个名词。
局部循环体控制变量用i,j,k。如for(i=0;i<100;i++)。
指针变量用“p_”开头,后面接指向内容。如指向高度变量的指针,命名为“*p_height”。请读者自行区分指针和指针变量的区别。
局部变量尽量用一个单词表达清其含义。
全局变量命名时首先写所属模块名称。例如如一个传感器文件sensor.c里面的一个全局变量要代表温度,则命名为sensor_temperature。又例如LCD(液晶显示屏)文件LCD.c中表示LCD状态的全局变量命名为LCD_status。因为全局变量往往跨文件调用,如不写清变量定义位置,当程序庞大,而IDE又不支持一键定位时,查找起来很麻烦。即使IDE支持一键定位,一个清楚明白的命名,能让人瞬间读懂该变量的含义。
2)数组命名
数组命名各单词首字母大写,其他同变量。
读者可能会有疑问,数组名后面会有[]符号,与变量区别明显,为什么要用首字母大写的方式。实际上,在数组名作为实参传递数组首地址时,往往会省略[]符号,应该数组名就是数组的首地址。例如:
unsigned char string[]=”abcdefg”;
printf(“%s”,string);
在以上代码中,string是一个8位数组(为什么是8位?),在使用printf()函数输出时,只写了数组名,显然这种方式是被允许的。而此时就没有写[],在这种情况下,并不能瞬间知道string是变量还是数组,而需要参考前面的格式控制符“%s”。在其他函数中,或许没有“%s”这样的格式控制符帮助我们判断string到底是数组还是变量,我们只有找到函数的声明或定义才能知道答案,严重影响阅读。因此有必要对数组和变量加以区分。
3)函数命名
函数命名各单词首字母大写,写成主谓语形式,主语用名词,谓语用动词,缩写词汇用大写,用“_”表从属关系。主语通常为模块名,而谓语是描述模块的动作。因为函数本身就是用来执行一系列的动作的, 结合函数参数,可以表达通顺的语句。举个简单的例子:延时函数。定义一个ms级延时函数为:
void Delay(unsigned int ms);
当然,函数命名中必要时可以出现宾语。这种情况多出现在函数没有参数的情况下。如一个函数的功能是LCD显示时间,而时间是全局变量,因此这个函数就不需要参数,此时直接定义成void LCD_Display_Time(void)(其实是声明,因为没写函数体)。
4)标号命名
由于在硬件编程中标号可以用循环来代替,所以很少用到。我们规定标号的命名格式基本同变量,使用全部小写的名词,但是只用一个单词表示即可。因为标号时候的时候或者前面加了goto,或者后面加了“:”,很容易与变量区分开。况且只是一个定位标志,所以一个单词足够了。
5)自定义类型命名
自定义类型命名主要指使用typedef定义的新类型名,以及结构体类型、共用体类型的类型名(而非该类型的变量名)。
自定义的新类型名,只用一个单词,首字母大写。但是定义这种新类型的变量时,命名规则与变量命名规则完全相同。
请自行体会新类型名与新类型变量的区别。
6)宏定义命名
宏定义命名全部使用大写字母,单词数不限。可以加入数字和下划线,但是数字不能开头 。
由于宏定义的特殊性,对其使用名词或动词不作规定。因为宏定义一个函数时,应该是动词性质,而宏定义一个常数时,应该是名词性质。
3、表达式的书写
操作数与运算符之间要有空格隔开,以便于区分。
4、文件编写
(1)、文件按模块划分,函数按功能划分。
(2)、
源文件(.c) |
头文件(.h) |
头文件包含指令(#include) |
头文件包含指令(#include) |
|
宏定义(#define) |
所有函数定义(必须有函数体,即{ }) 内部函数声明(static,不能有函数体) |
外部函数声明(extern,不能有函数体) |
外部变量定义(必须赋初值) 静态外部变量定义(static,必须赋初值) |
外部变量声明(extern,不能赋值)
|
|
自定义类型(typedef) |
外部数组定义 静态内部数组定义(static) |
外部数组声明(const) |
条件编译 |
条件编译 |
由上表可以看出,h文件内存放的都是对外可见的变量、函数数组等的声明,宏定义则是对内对外都可以使用,放在这里主要为了修改方便。
在定义外部变量、数组和函数时,不需要写extern,因为缺省时默认extern。而声明外部变量、数组和函数时,必须用extern显式声明,这样是为了让代码更直观。
(3)、函数头部注释格式
/********************************************************
*名 称: function(int par)
*功 能:**
*入口参数:**
*出口参数:**
*说 明:
********************************************************/
借鉴了一些良好的编程风格:http://www.cnblogs.com/foxsay/p/5331388.html