1、目录一. 与平台或者编译器有关的准则 .1二. 与命名有关的准则 2三. 程序的版式 3四. 表达式和基本语句 6五. 函数设计 8版本修改历史版本 作者/修改人 修改时间 修改内容V 0.01 庞军 2011/10/19 起草 C 语言代码规范一. 与平台或者编译器有关的准则1.1 在变量申明时,不要用非常量初始化数组。并不是所有的编译器都支持用变量初始化数组。/ 不要使用这种风格int fun(int iSize)int arrayiSize;1.2 不要使用 0 长度的数组。并不是所有的编译器都支持 0 长度的数组。1.3 不要在代码中间定义变量,在函数开始处申明变量。并不是所有的编译器
2、都支持在代码中定义变量。1.4 不要使用匿名的 union。并不是所有的编译器都支持匿名的 union。typedef struct foo int foo;union int foo_l;float foo_s; u; /* have a name here */ foo_t;1.5 不要使用“uchar“, “u_char“, “ushort“, “u_short“, “uint“, “u_int“, “ulong“, “u_long“, “boolean“等类型。这些类型并不是标准的 C 语言类型。1.6 不要把 long 类型等同于 signed 64-bit 整形,不要把 unsig
3、ned long 类型等同于 unsigned 64 bit 整形。Long 类型的大小与平台有关,在 32 位平台上 long 是 32 位的。1.7 不要使用非 ASCII 字符写代码。1.8 不要使用 “bzero()“, “bcopy()“, “bcmp()“等函数,这些函数已经被标明为过时的,在以后的 C 库中可能不在支持以上函数。应该使用”memset()”, “memcpy()”, “memmove()”, “memcmp()”1.9 在多线程环境下,不要使用不是线程安全的函数。例如,在 linux 下,不要使用”ctime()”, “gmtime()”, “localtime(
4、)” 等函数,而应该使用 “ctime_r()”, “gmtime_r()”, “localtime_r()”函数线程安全的函数。1.10 不要使用 “strcpy()“, “strcmp()“, “sprintf()“等函数,这些函数会带来安全隐患,很多缓冲区溢出攻击都是利用这些函数的漏洞。应该使用”strncpy()”, “strncmp()”, “snprintf()”1.11 不要在栈空间中分配大量内存,应该使用动态内存。因为栈空间是有限的,但动态内存相对栈空间来说是无限的。1.12 不设计递归函数。因为递归函数容易耗尽栈空间。1.13 不要在函数中返回指向栈空间的指针。在函数返回时栈
5、空间会被释放,指向栈空间的指针将变成非法指针。void *foo()char buf1024;return buff;1.14 将编译器的警告级别调到最高。很多 BUG 是由这些警告引起的。二. 与命名有关的准则2.1 标识符最好采用英文单词或其组合。标识符不能使用中文字符。2.2 标识符的长度应当符合 ”min-length int iMaxValue;int getValue();void setValue(int iValue);2.7 类型名以大写字母开头的字词组合而成。struct MeterInfo;enum MeterType;2.8 常量全用大写的字母命名,并用下划线分割单词。
6、#define MAX_LENGTH (100)2.9 静态变量加前缀 “s_” (表示 static) 。2.10 全局变量加前缀 “g_” (表示 global) 。static int s_iCounter;int g_iMeterNum;三. 程序的版式3.1 将代码编辑器设置成用 4 个空格代替 tab3.2 将编辑器的缩进设置成 4 个空格3.3 在每个函数定义结束之后都要加空行。3.4 在每个函数体内,逻辑上密切相关的语句之间不加空行,其它地方应该加空行分隔。/ 空行void Function1()/ 空行/ 空行while (condition)statement1;/ 空行i
7、f (condition)void Function2()/ 空行void Function3()statement2;elsestatement3;/ 空行statement4;3.5 一行代码只做一件事情,如只定义一个变量,或只写一条语句。3.6 if、for、while、do、等语句独占一行,执行语句不得紧跟其后。执行语句有多少都要加。风格良好的代码行 风格不良好的代码行int width; / 宽度int height; / 高度int depth; / 深度int width, height, depth; / 宽度高度深度x = a + b;y = c + d;z = e + f;
8、x = a + b; y = c + d; z = e + f;if (width =”、 “”这类操作符前后不加空格。void func(int x, int y, int z); / 良好的风格void func (int x,int y,int z); / 不良的风格if (year = 2000) / 良好的风格if(year=2000) / 不良的风格if (a = b) / 不要写成 b - Function();3.13 程序的分界符和应独占一行并且位于同一列,同时与引用它们的语句左对齐。3.14 之内的代码块在右边数格处左对齐。风格良好的对齐 为风格不良的对齐void Func
9、tion(int x)int iMin;int iMax; / program codevoid Function(int x) / program codeif (condition) / program codeelse / program codeif (condition) / program codeelse / program codefor (initialization; condition; update) / program codewhile (condition) / program codefor (initialization; condition; update)
10、 / program codewhile (condition) / program code如果出现嵌套的 ,则使用缩进对齐,如:3.15 代码行最大长度宜控制在 80 个字符以内。3.16 长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符) 。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。if (very_longer_variable1 = very_longer_variable12)col5; col+ )for (row=0; row100; row+)sum = sum + arowcol;for (i=0; iN; i+)if (conditio
11、n)DoSomething();elseDoOtherthing();if (condition)for (i=0; iN; i+)DoSomething();elsefor (i=0; iN; i+)DoOtherthing();4.7 不可在 for 循环体内修改循环变量,防止 for 循环失去控制。4.8 建议 for 语句的循环控制变量的取值采用“半开半闭区间”写法。4.9 每个 case 语句的结尾不要忘了加 break,否则将导致多个分支重叠(除非有意使多个分支重叠) 。4.10 不要忘记最后那个 default 分支。即使程序真的不需要 default 处理,也应该保留语句 de
12、fault : break; 这样做并非多此一举,而是为了防止别人误以为你忘了 default 处理。4.11 不要使用 goto 语句。五. 函数设计5.1 参数的书写要完整,不要贪图省事只写参数的类型而省略参数名字。void setValue(int width, int height); / 良好的风格void setValue(int, int); / 不良的风格5.2 参数命名要恰当,顺序要合理。例如void stringCopy(char *str1, char *str2);那么我们很难搞清楚究竟是把 str1 拷贝到 str2 中,还是刚好倒过来。可以把参数名字起得更有意义,如
13、叫 pSource 和 pDestination。这样从名字上就可以看出应该把 pSource 拷贝到 pDestination。还有一个问题,这两个参数那一个该在前那一个该在后?参数的顺序要遵循标准 C 函数的命名习惯。一般地,应将目的参数放在前面,源参数放在后面。5.3 如果参数是指针,且仅作输入用,则应在类型前加 const,以防止该指针在函数体内被意外修改。void stringCopy(char *pDestination,const char *pSource);5.4 避免函数有太多的参数,参数个数尽量控制在 5 个以内。如果参数太多,在使用时容易将参数类型或顺序搞错。5.5 不
14、要将正常值和错误标志混在一起返回。正常值用输出参数获得,而错误标志用 return 语句返回。5.6 函数的功能要单一,不要设计多用途的函数。5.7 函数体的规模要小,尽量控制在 80 行代码之内。5.8 尽量将函数设计为只有一个输入和一个输出。5.9 尽量避免函数带有“记忆”功能。相同的输入应当产生相同的输出。带有“记忆”功能的函数,其行为可能是不可预测的,因为它的行为可能取决于某种“记忆状态” 。这样的函数既不易理解又不利于测试和维护。在 C/C+语言中,函数的 static 局部变量是函数的“记忆”存储器。建议尽量少用 static 局部变量,除非必需。5.10 在函数体的“入口处” ,对参数的有效性进行检查。5.11 不仅要检查输入参数的有效性,还要检查通过其它途径进入函数体内的变量的有效性,例如全局变量、文件句柄等。5.12 如果所定义的函数不是全局函数,则应将该函数申明为 static。