<规则2> 定义公共指针的同时对其初始化。
这样便于指针的合法性检查,防止应用未经初始化的指针。建议对局部指针也在定义的同时初始化,形成习惯。
<规则3> 较大的局部变量(2K以上)应声明成静态类型(static),避免占用太多的堆栈空间。
避免发生堆栈溢出,出现不可预知的软件故障。 <规则4> 防止内存操作越界。
说明:内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。 A.数组越界。 char aMyArray[10]; for( i = 0; i <= 10; i++ ) {
aMyArray[i] = 0; //当i等于10时,将发生越界。 }
B.指针操作越界。 char aMyArray[10]; char *pMyArray; pMyArray = aMyArray; --pMyArray; // 越界 pMyArray = aMyArray; pMyArray += 10; // 越界
<规则5> 减少没必要的指针使用,特别是较复杂的指针,如指针的指针、数组的指针,指针的数组,函数的指针等。
用指针虽然灵活,但也对程序的稳定性造成一定威胁,主要原因是当要操作一个指针时,此指针可能正指向一个非法的地址。安安全全地使用一个指针并不是一件容易的事情。
<规则6> 防止引用已经释放的内存空间。
在实际编程过程中,稍不留心就会出现在一个模块中释放了某个内存块(如指针),而另一模块在随后的某个时刻又使用了它。要防止这种情况发生。
<规则7> 程序中分配的内存、申请的文件句柄,在不用时应及时释放或关闭。 分配的内存不释放以及文件句柄不关闭,是较常见的错误,而且稍不注意就有可能发生。这类错误往往会引起很严重后果,且难以定位。
<规则8> 注意变量的有效取值范围,防止表达式出现上溢或下溢。 示例:
unsigned char cIndex = 10; while( cIndex-- >= 0 ) {
} //将出现下溢
当cIndex等于0 时,再减1不会小于0,而是0xFF,故程序是一个死循环。 char chr = 127;
chr += 1; //127为chr的边界值,再加1将使chr上溢到-128,而不是128。 <规则9> 防止精度损失。 以下代码将产生精度丢失。
#define DELAY_MILLISECONDS 10000 char time;
time = DELAY_MILLISECONDS; WaitTime( time );
代码的本意是想产生10秒钟的延时,然而由于time为字符型变量,只取DELAY_MILLISECONDS的低字节,高位字节将丢失,结果只产生了16毫秒的延时。 <规则10> 防止操易混淆的操作符拼写错误。
形式相近的操作符最容易引起误用,如C/C++中的“=与==\与||\与\等,
示例:如把“&\写成\
bRetFlag = ( pMsg -> bRetFlag & RETURN_MASK ) ; 被写为:
bRetFlag = ( pMsg -> bRetFlag && RETURN_MASK ) ; <规则11> 使用无符号类型定义位域变量。 示例: typedef struct { int bit1 : 1; int bit2 : 1; int bit3 : 1; } bit; bit.bit1 = 1; bit.bit2 = 3; bit.bit3 = 6;
printf(\ 输出结果为:-1,-1, -2,不是: 1,3,6.
<规则12> switch语句的程序块中必须有default语句。
对不期望的情况(包括异常情况)进行处理,保证程序逻辑严谨。
<规则13> 当声明用于分布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序,使用的位域也要有充分的考虑。
比如Intel CPU与68360 CPU,在处理位域及整数时,其在内存存放的撍承驍,正好相反。
示例:假如有如下短整数及结构。 unsigned short int exam ;
typedef struct _EXAM_BIT_STRU { /* Intel 68360 */
unsigned int A1 : 1 ; /* bit 0 2 */ unsigned int A2 : 1 ; /* bit 1 1 */ unsigned int A3 : 1 ; /* bit 2 0 */ } _EXAM_BIT ;
如下是Intel CPU生成短整数及位域的方式。 内存: 0 1 2 ... (从低到高,以字节为单位) exam exam低字节 exam高字节 内存: 0 bit 1 bit 2 bit ... (字节的各撐粩) _EXAM_BIT A1 A2 A3
如下是68360 CPU生成短整数及位域的方式。 内存: 0 1 2 ... (从低到高,以字节为单位) exam exam高字节 exam低字节 内存: 0 bit 1 bit 2 bit ... (字节的各撐粩) _EXAM_BIT A3 A2 A1
<规则14> 编写可重入函数时,应注意局部变量的使用(如编写C/C++语言的可重入函数时,应使用auto即缺省态局部变量或寄存器变量)。
可重入性是指函数可以被多个任务进程调用。在多任务操 作系统中,函数是否具有可重入性是非常重要的,因为这是多个进程可以共用此函数的必要条件。另外,编译器是否提供可重入函数库,与它所服务的操作系统有 关,只有操作系统是多任务时,编译器才有可能提供可重入函数库。如DOS下BC和MSC等就不具备可重入函数库,因为DOS是单用户单任务操作系统。
编写C/C++语言的可重入函数时,不应使用static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。
<规则15> 编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护。
<规则16> 结构中的位域应尽可能相邻。结构中的位域在开始处应对齐撟纸跀或撟謹的边界。
这样可减少结构占用的内存空间,减少CPU处理位域的时间,提高程序效率。 示例:如下结构中的位域布局不合理。(假设例子在Intel CPU环境下) typedef struct _EXAMPLE_STRU {
unsigned int nExamOne : 6 ;
unsigned int nExamTwo : 3 ; // 此位域跨越字节摻唤訑处。 unsigned int nExamThree : 4 ; } _EXAMPLE ;
应改为如下(按字节对齐)。 typedef struct _EXAMPLE_STRU {
unsigned int nExamOne : 6 ;
unsigned int nFreeOne : 2 ; // 保留bit位,使下个位域从字节开始。 unsigned int nExamTwo : 3 ; // 此位域从新的字节处开始。 unsigned int nExamThree : 4 ; } _EXAMPLE ;
<规则17> 避免函数中不必要语句,防止程序中的垃圾代码,预留代码应以注释的方式出现。
程序中的垃圾代码不仅占用额外的空间,而且还常常影响程序的功能与性能,很可能给程序的测试、维护等造成不必要的麻烦。
<规则18> 通过对系统数据结构的划分与组织的改进,以及对程序算法的优化来提高空间效率。
这种方式是解决软件空间效率的根本办法。