分类: C/C++
2009-10-13 11:14:08
5.变量(11条规则)
【规则
【规则
【规则
【规则
【规则
例如:
int array[]={1,2,3,4,5};
在需要使用数组长度时,用sizeof(array)/sizeof(array[0])计算得出。
【规则
【规则
【规则
例如:
int Function(const char* pChar ) {
int *pInt=(const int*)pChar;/*危险操作*/
return(*pInt);
}
【规则
【规则
【规则
6.表达式和基本语句(17条规则+3条建议)
6.1 运算符的优先级(1条规则)
【规则
例如:
value = (high << 8) | low
if ((a | b) && (a & c) )
6.2 复合表达式(4条规则)
如a=b=c=0这样的表达式称为复合表达式。允许复合表达式存在的理由是:
(1)书写简洁;
(2)可以提高编译效率;
(3)但要防止滥用复合表达式。
【规则
例如:i=a>= b && c
【规则
例如:d=(a=b+c)+r ; //该表达式既求a 值又求d 值。
应该拆分为两个独立的语句:
a=b+c;
d=a+r;
【规则
例如: if( a是数学表达式而不是复合表达式并不表示 if( (a而是成了令人费解的 if( (a
【规则
例如:
int i = 0, a[5];
a = i++; // 给a[0]赋值还是给a[1]赋值?
6.3 if 语句布尔表达式(7条规则)
if 语句是C 语言中最简单、最常用的语句,然而很多程序员用隐含错误的方式写if 语句。
【规则
例如:
if( 0!=(a+b)%6 ) {
}
【规则
例如:
if( x>y ) { //左括号不另起一行 } Else { //左括号不另起一行 if ( y>z) { } Else { } } |
【规则
例如:
int a=10; int b=0; int c=0; if( 0!==a && 0!=b && 0!=c ){ } Else { x=y/c; } |
【规则
例如:
int a=10; int b=0; int c=0; if( 0!==a || 0!=b || 0!=c ){ x=y/c; } |
【规则
根据布尔类型的语义,零值为“假”(记为FALSE),任何非零值都是“真”(记为TRUE)。TRUE 的值究竟是什么并没有统一的标准。例如Visual C++ 将TRUE 定义为1,而Visual Basic 则将TRUE 定义为-1。
假设布尔变量名字为flag,它与零值比较的标准if 语句如下:
if( flag ) /* 表示flag 为真*/
if( !flag ) /* 表示flag 为假*/
其它的用法都属于不良风格,例如:
if( flag == TRUE )
if( flag == 1 )
if( flag == FALSE )
if( flag == 0 )
【规则
千万要留意,无论是float 还是double 类型的变量,都有精度限制。所以一定要避免将浮点变量用“==”或“!=”与数字比较,应该设法转化成“>=”或“<=”的形式。假设浮点变量为x,应当将
if( x == 0.0 ) // 隐含错误的比较
转化为
if( (x>=-EPSINON ) && ( x<=EPSINON) )
其中EPSINON 是允许的误差(即精度)。
【规则
指针变量的零值是“空”(记为NULL)。尽管NULL 的值与0 相同,但是两者意义不同。假设指针变量的名字为p,它与零值比较的标准if 语句如下:
if( p== NULL ) // p 与NULL 显式比较,强调p 是指针变量
if( p!= NULL )
不要写成
if( p==0 ) // 容易让人误解p 是整型变量
if( p!=0 )
或者
if( p ) // 容易让人误解p 是布尔变量
if( !p )
6.4 循环语句(1条规则+3条建议)
C语言的循环语句中,for 语句的使用频率最高,while 语句其次,do 语句很少用。本节重点论述循环体的效率。提高循环体效率的基本办法是降低循环体的复杂性。
【规则
【建议
低效率:长循环在最外层 |
高效率:长循环在最内层 |
for ( row=0; row<100; row++ ) { for ( col=0; col<5; col++ ) { sum = sum + a[row][col]; } } |
for ( col=0; col<5; col++ ) { for ( row=0; row<100; row++ ) { sum = sum + a[row][col]; } } |
【建议
a、效率低但程序简洁 |
b、效率高但程序不简洁 |
for( i=0; i if ( condition ) DoSomething(); else DoOtherthing(); } |
if( condition ) { for( i=0; i DoSomething(); } Else { for(i=0; i DoOtherthing(); } |
【建议
示例a中的x 值属于半开半闭区间“0 =< x < N”,起点到终点的间隔为N,循环次数为N。
示例b中的x 值属于闭区间“0 =< x <= N
相比之下,示例a的写法更加直观,尽管两者的功能是相同的。
a、循环变量属于半开半闭区间 |
b、循环变量属于闭区间 |
for( x=0; x ... } |
for( x=0; x<=N-1; x++ ) { ... } |
6.5 switch 语句(2条规则)
【规则
【规则
6.6 goto 语句(1条规则)
【规则
7.函数设计(17条规则+10条建议)
7.1注释规则(1条规则)
【规则
一个函数的注释信息如下例:
/********************************************************************************** *Function(功能):calculate The area of rectangle * *parameter(参数):the Length and Width of rectangle * *outout(返回值):the area of rectangle * ********************************************************** ************************/ int GetValue(int iLength, int iWidth) { … return iArea; } /* Error: 1描述在单元测试中出现的错误 2… */ |
7.2 函数的使用(1条规则)
【规则
7.3 参数的规则(4条规则+2条建议)
【规则
例如:
void SetValue(int width, int height); // 良好的风格
void SetValue(int, int); // 不良的风格
float GetValue(void); // 良好的风格
float GetValue(); // 不良的风格
【规则
例如:
编写字符串拷贝函数StringCopy,它有两个参数。如果把参数名字起为str1和str2。
例如:
void StringCopy(char *str1, char *str2);
很难搞清楚究竟是把str1 拷贝到str2 中,还是相反。可以把参数名字起得更有意义,例如strSource 和strDestination。这样从名字上就可以看出应该把strSource 拷贝到strDestination中。另外,参数的顺序要遵循库函数的风格。一般地,应将目的参数放在前面,源参数放在后面。
【规则
例如:
void StringCopy(char *strDestination,const char *strSource);
【规则
【建议
【建议
7.4 返回值的规则(6条规则)
【规则
【规则
【规则
【规则
函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有任何价值。
【规则
【规则
7.5 函数内部实现的规则(2条规则)
不同功能的函数其内部实现各不相同,看起来似乎无法就“内部实现”达成一致的观点。但根据经验,我们可以在函数体的“入口处”和“出口处”从严把关,从而提高函数的质量。
【规则
【规则
注意事项如下:
(1)return 语句不可返回指向“栈内存”的“指针”,因为该内存在函数体结束时被自动销毁。
例如:
char * Func(void) {
char str[] = “hello student”; // str 的内存位于栈上
…
return str; // 将导致错误
}
(2)要搞清楚返回的究竟是“值”还是“指针”。
7.6 其它建议(6条建议)
【建议
【建议
【建议
【建议
【建议
【建议
7.7 使用断言(2条规则+2条建议)
程序一般分为Debug 版本和Release 版本,Debug 版本用于内部调试,Release 版本发行给用户使用。
断言assert 是仅在Debug 中版本起作用的宏,它用于检查“不应该”发生的情况。在程序运行过程中,如果assert 的参数为假,那么程序就会中止(一般还会出现提示对话,说明在什么地方引发了assert)。
assert 不是一个仓促拼凑起来的宏。为了不在程序的Debug 版本和Release 版本引起差别,assert 不应该产生任何副作用。所以assert 不是函数,而是宏。程序员可以把assert 看成一个在任何系统状态下都可以安全使用的无害测试手段。如果程序在assert处终止了,并不是说明含有该assert 的函数有错误,而是调用者出了差错,assert 可以帮助我们找到发生错误的原因。
【规则
【规则
【建议
【建议
8.内存管理(5条规则)
8.1 内存使用注意的问题(5条规则)
内存分配方式有三种:
(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
(2)在栈上分配。在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配,亦称动态内存分配。程序在运行时用malloc或calloc申请任意大小的内存,程序员自己负责在何时用free释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。
【规则
【规则
【规则
【规则
【规则
9.其他规范及建议(27条建议)
9.1 提高程序的效率(6条建议)
程序的时间效率是指运行速度,空间效率是指程序占用内存或者外存的状况。全局效率是指站在整个系统的角度上考虑的效率,局部效率是指站在模块或函数角度上考虑的效率。
【建议
【建议
【建议
【建议
【建议
【建议
9.2 编译问题(2条建议)
【建议
【建议
9.3 兼容性问题(8条建议)
【建议
【建议
【建议
【建议
【建议
【建议
【建议
【建议
9.4性能问题(4条建议)
【建议
【建议
【建议
【建议
9.5 其他一些有益的建议(7条建议)
【建议
【建议
【建议
【建议
【建议
【建议
【建议