|
C语言,无论是在程序书写格式上还是语法的使用上为我们提供了很大的自由。如果不加一点限定,就会使程序员风格各异,不便于交流和理解,还会阻碍代码的使用、移植、维护和审查。
本文参考了许多成熟的编程约定,取其精华,并结合我们电机控制软件的特殊性而制定。坚持下面约定,统一风格,养成习惯,可以减少阅读别人程序时不必要的疑惑,减少自己编程时的犹豫。您以后的编程中会不假思索而且合理地定义出变量、函数,而且您也不会犹豫使用何种书写风格了。
“首先为人编写程序,其次才是计算机”—Steve McConnell[7]
1 命名规则
1.1 命名通则
l 全部使用英语单词或单词的缩写组合起来, 对函数、变量等进行命名。
l 用单词紧挨着的形式,中间的单词大写开头,变量最前面的单词要小写开头。
l 缩写名词当普通名词对待。在规定小写开头和大写开头的地方也不再全部大写。这可以防止和常量名混淆。如“PWM”有时也要写成“pwm”(变量)或“Pwm”。
l 少用数字来标识。不要起诸如“zhang3, Li4,a、b、c”类的变量名。
l 不要短于两个字符。作用范围很小的局部变量可以用一个字符,如“i”。
l 最好起容易念出的名字。不要起如:“WmHsi”类似的名字。为的是便于交流。
l 建议“不要单纯通过大写来区分命名”。有了大小写的约定,这条约定似乎没用了。
1.2 后缀和前缀
l 前缀:可用来区别变量、函数、文字等所属的软件模块;
例:
l 后缀:可用来表示属性或类型
例:
l 前缀后缀大小写规则遵从函数或变量等的命名规则
l 定标值后加后缀“Q”以示区别
l 上一次的值直接加后缀“Old”以示区别
l 指针变量加后缀“Ptr”。
l 临时变量用“Tmp”作后缀。
1.3 变量名
l 小写开头,中间单词大写开头(Rs,Lm等变量也写成rs,lm)。
l 子函数中的局部变量加“L”后缀。
l 中间不要加“_”,原因:不支持编辑双击选中单词功能,视觉混乱,增加名字的长度,并且中间单词大写开头已经能区分各个单词。
1.4 函数名大写开头
l 大写开头,其中间单词大写开头。
l 函数名中,尽量将动词放在前面,名词放在后面。例如InitBoard() 而不是BoardInit()。
l 中间不要加“_”
1.5 中间变量的惯例:
l i, j和k 代表循环变量
l p1, p2,…, pn 代表指针
l c, c1, …, cn 代表字符
l s, s1, …, sn 代表字符串
l n 代表数量
l ix, iy和iz 代表中间整型变量
l fx, fy和fz 代表中间浮点变量
1.6 自定义的数据类型
l struct, union名称全部大写。
l 其实例大写开头(如TI的例程)
l 全部大写的两大坏处:不好手写,不好辨认。
1.7 常量和宏
l 常量和宏全部大写,并用下划线来分开不同的单词。
l 不用直接使用数字而是定义常量。原因:可读性变差;多处输入数字输入错误的可能性变大;改动需要多处改动。
l 不许采用非独立常数定义,如果可以由其他常量导出,就一定使用导出。改动时可以一改全改。
2 类型的使用和类型转换
2.1 数据类型使用:
l 禁止使用长度不定的int和float型,用short和long以及double型代替。
2.2 我们只使用3种数据类型,short,unsigned short, long
l 能使用unsigned 类型的地方尽量使用,用unsigned short可以更充分利用16位数的表示范围
l 能用long的地方尽量不用unsigned long,因为long的表示范围已经足够了。
2.3 如果要进行数据类型转换最好显式地写出,不要让编译器自动转换。
3 嵌入汇编
3.1 嵌入汇编要注意维护C语言默认的环境
l C语言默认的语言环境是:详见TI资料:spru514.pdf第七章
4 函数
4.1 函数为void型和参数为void型都要显式写出void;
l void function()是不良的风格,应作void function(void)。
4.2 建议函数中尽量不用static静态变量。
4.3 函数的参数的顺序:目的操作数,源操作数,其他。
l 这样和y=sin(x)中的返回值和输入的顺序一致。
例:void Mux(short *pOut, short input0, short input1, short select);此例中的多路开关程序的参数顺序是:输出,输入和其他。
4.4 不得用模块的输入输出变量兼做中间变量。
l 因为这些参数可能被异步地使用。
例:计算功率的程序
void pwCalc(void)//参数全部使用全局变量;
{
p = ual * ial;//这是错误的写法,若此程序从这里被中断,则使用全局变量p会得到错误的结果
p += ube * ibe;
}
应改成这样:
{
p = ual * ial + ube * ibe;//这是正确的写法
}
4.5 关于全局临时变量:
l 中断和主程序中分别设立临时变量;这样可以不保护临时变量。
5 初始化
5.1 尽量在定义变量的同时初始化该变量(就近原则)
l 减少隐患,防止忘了初始化而导致出错。
5.2 所有变量的初始状态为0, 除非特别加以赋值
6 表达式和控制流程
6.1 不要在一行中使用多个复杂形式的赋值语句(如x = y = z =1;)。
6.2 不写多用途的表达式:
l 如d=(a=b+c)+e;
6.3 对于for循环,建议采用半开半闭的写法。
l 如:for(i=0; i<num; i++),这样循环次数正好等于num。
6.4 switch case 最好加上default,保持完整性
l
7 书写格式
7.1 空格与空行
l 函数名和参数列表的圆括弧间不要加空格,即“紧跟函数名”。
l 关键词if, for, while,do和switch后跟一个空格,以突出关键字。
l 关键词else在它之前和之后各加一个空格
l 下列运算符书写时中间没有空格;“-> ”结构指针运算符;“.”结构成员运算符;“[ ]” 数组下标。建议修饰符“*”、“&”紧靠变量名。
l 括弧中的表达式在括弧开始和结束时不应有空格。如: strcat(t, s, n)
l 建议逗号和分号要“前无空格,后有空格”。如: for (i = 0; i < n; i++)
l 一元操作符和操作数之间不应有空格;
l 如:!p ~b ++i (long)m *p &x sizeof(k)
l 建议二元操作符和操作数之间用一个和多个空格分开,三元操作符也一样:
l 如: c1 = c 2 x + y i += 2 n > 0 ? n : -n;
l 建议在适当的地方(函数之间,声明和定义之间)加空行,目的是使段落清晰。
7.2 大括号:
l 一:在子程序中,大括号各占一行;在if 等关键字后面紧跟“{”,在段落结束的下一行用“}”,在if,else结构中,有“} else {”的形式。“}”要和对应的关键字的开头处于同一列。
l void RsTrigLoActR(Uint16 *pQ, Uint16 reset, Uint16 set)
l {
l if (reset == 0){
l *pQ = 0;
l } else if (set == 0) {
l *pQ = 1;
l } else {
l *pQ = *pQ;
l }
l }
l 二:全部大括号都独立占一行(虽然代码占用篇幅较长,但是看起来整齐)。 “{”和“}”要和对应的关键字的开头处于同一列。
l void RsTrigLoActR(Uint16 *pQ, Uint16 reset, Uint16 set)
l {
l if (reset == 0)
l {
l *pQ = 0;
l }
l else if (set == 0)
l {
l *pQ = 1;
l }
l else
l {
l *pQ = *pQ;
l }
l }
l 上述两种都可以,但每个程序员必须一直保持自己的使用风格,在单个函数中不能混用这两种方式。
l 例外:在do-while循环、struct和union的定义中,“}”不单独占一行。
l if, for, while,do的执行语句不论多么短,都必须加大括号;这样才清晰,并且再加几条执行语句时不用补大括号了。
l if的使用:一个不良的风格(不便阅读):
l if(condition)
return x;
l return y;
l 好的习惯如:
l if(condition){
l return x;
l } else {
l return y;
l }
7.3 一行只干一件事,便于阅读写注释。
l 每个变量声明都占一行。
l 一个语句占一行。
l 把if(条件)写在一行,而把要执行的语句放在下一行。不论执行语句多短也不要放在一行,不为别的,只为统一风格,便于阅读。
7.4 缩进与对齐
l 四个空格来缩进:因为两个太少,8个太多。
l 不许用tab键。因为不同的编辑器对tab的显示方法可能不同。
l 同一段落的程序开头对齐。
8 注释
8.1 我们的目标是:“追求自文档化程序,没有冗余信息”。
8.2 文件开头的说明和版本历史
l 参考TI例程的方法
l 给出程序的执行时间:分有分支程序和无分支程序两种。有分支程序要给出最长的分支时间
8.3 当需要大量注释时,它们经常写在函数头部的描述中。
l /* */为段注释,注意不要嵌套着用,那会出问题,不信可以试试。
l //为行注释
8.4 单行注释和被注释的行开头对齐
8.5 代码行修改后要在行后加注释,注明修改日期、修改人员、所做变动。格式如下:
l //……,(yymmdd,姓名全拼,改动处)
l 例如://……,(030531,chenlin,修改了……)
8.6 注释用词要精确、简洁,切中要害,不能有二义性
8.7 避免冗余信息
l 注释中避免写些容易变化的信息,减少维护代价。防止代码变更后还得改注释。
l 下面这句注释就写了易变化的信息
l if (attempts > 12) //尝试不要多于12次;
l 改成下面这样就好多了
l if (attempts > 12)//限制尝试的次数 |
|