一个过程名禁止被重用于其它之处。
例如:
void foo (unsigned int p_1)
{
unsigned int x=p_1;
}
/***********
* 过程名禁止被重用
***********/
void static_p (void)
{
unsigned int foo=lu;
}
一个标号名被重用掩盖了这个标号名的含义。出现这种情况时,编译是否通过是依赖于编译器的差异而不同。
例如:
/***********
*标号名禁止被重用
***********/
void static_p (void)
{
unsigned int value_x=lu;
unsigned int y=0u;
/*...*/
value_x:
y=lu;
/*...*/
}
在结构体定义中禁止含有空域。该准则的违背通常是出现在类似于如下的使用中:struct atag {struct anothertag {...}; ...};
例如:
/***********
* 禁止在结构体定义中含有空域
**********/
struct s_p (unsigned int xs; struct (unsigned char ac, ab; }; };
void static_p (void)
{
struct s_p sb;
sb.xs=1;
/*...*/
}
使用多重标号是多余的,多重标号完全可以用一个标号来替代。
例如:
/***********
* 禁止声明多重标号
**********/
static void static_p (void)
{
start: begin:
/*...*/
}
虽然一些编译器允许缺省参数类型,但使用参数类型说明易于类型匹配的检查,因此参数必须使用类型声明。
例如:
/***********
*参数必须使用类型声明
**********/
unsigned int static_p(p_1)
{
unsigned int result;
/*...*/
result=p_1*2;
return result;
}
虽然大多数编译器允许在过程声明中省略任何的参数说明,但在过程声明中对参数进行说明易于对过程使用中参数类型匹配的检查,因此在过程声明中必须对参数说明。
例如:
/***********
* 在过程声明中必须对参数说明
**********/
int static_p();
int static_p (unsigned int p)
{
int x=1;
/*...*/
if (p==0)
{
x=0;
}
return x;
}
一些编译器允许过程参数的说明只有类型而没有标识符,但这样的参数并不能真正地被使用,因此禁止过程参数只有类型没有标识符。
例如:
struct s_type_b {unsigned int xs;};
/***********
* 禁止过程参数只有类型没有标识符
**********/
void static_p_a (unsigned int p_1, struct s_type_b *);
void static_p_a (unsigned int p_1, struct s_type_b *)
{
/*...*/
}
过程参数用省略号说明不利于对参数匹配的分析,因此禁止在过程参数表中使用省略号。
例如:
/***********
* 禁止在过程参数表中使用省略号
**********/
unsigned int static_p (unsigned char* p_1, ...)
{
/*...*/
return lu;
}
重新定义使用C或C++的关键字,破坏了程序的可读性,因此禁止重新定义使用C或C++的关键字。
例如:
/***********
* 禁止重新定义使用C或C++关键字
**********/
void static_p (void)
{
unsigned int public =0;
unsigned int private =0;
unsigned int protected =0;
unsigned int operator =0;
unsigned int new =0:
unsigned int template =0;
unsigned int virtual =0;
unsigned int delete =0;
unsigned int friend =0;
unsigned int cout =0;
unsigned int cin =0;
unsigned int endl =0;
/*...*/
}
如果是一个无参数过程或函数,必须使用func(void)
的形式说明,禁止使用func()
的形式说明。
例如:
/***********
* 禁止过程或函数中的参数表为空
**********/
void satic_p ( )
{
/*...*/
}
在同一个宏中使用多于一个的#或##,或同时使用#和##都是很危险的,因此禁止在同一个宏中使用多个#或##。
定义带参数的宏(类函数宏)时,宏体必须用括号括起来。
例如:
#define IF_X (x) if(x){
/***********
*禁止定义不象函数的宏
**********/
void static_p (void)
{
bool test=true:
IF_X(test)
test=!test;
}
}
宏只能用于符号常量,类函数宏,类型限定符以及存储类说明。宏中不允许含有语句关键字和类型关键字。
例如:
/***********
* 禁止在宏中包含不允许的项
**********/
#define static_p unsigned int
void test_p (void)
{
static_p x=lu;
/*...*/
}
宏预处理可以重新定义保留字,但这种做法会引起混淆,因此禁止重新定义保留字。
例如:
/***********
* 禁止重新定义保留字
**********/
#define FILE unsigned int
void dummy (void)
{
/*...*/
}
若对字符型变量不明确定义是否有符号,则在执行时会作为有符号或无符号的类型使用,因此要求字符型变量必须明确定义是有符号还是无符号。
例如:
/***********
* 字符型变量必须明确定义是有符号还是无符号
**********/
void static_p (void)
{
char c=‘c’;
/*...*/
}
虽然C语言允许在许多不同的上下文中对一个名字重新定义,但命名的唯一性可使程序增加可读性,因此禁止对一个名字重新定义。
例如:
/***********
* 禁止对一个名字重新定义
**********/
unsigned int static_p (void);
struct static_p
{
unsigned int static_p;
unsigned int u_1 ;
};
unsigned int static_p (void)
{
unsigned int var_1;
/*...*/
static_p:
var_1=lu;
/*...*/
returm (var_1);
}
改变用户自定义的类型会引起混滑甚至能导致错误,因此用typedef自定义的类型禁止被重新定义。
例如:
typedef int mytype:
/**********
* 用typedef自定义的类型禁止被重新定义
**********/
void static_p (void)
{
typedef float mytype;
/*...*/
}
#if
而没有#endif
预处理语句的#if和#endif禁止分散在不同的文件之中。
禁止使用没有边界限定的数组定义。
例如:
/**********
* 禁止数组没有边界限定
**********/
void static_p (void)
{
unsigned int u_array[]={0, 1, 2};
/*...*/
}
#include<......>
中使用绝对路径名头文件路径应该在编译器的选项中予以设置说明,禁止在#include<......>
中使用绝对路径名。例如:
/**********
* 禁止在#include<......>中使用绝对路径名
**********/
#include <C:\VC\include\stdio.h>
void Dummy (void)
{
/*...*/
}
结构体的声明必须要完整地声明。
例如:
/**********
* 禁止结构体声明不完整
**********/
struct static_p;
void dummy (void)
{
/*...*/
}
在参数表的参数声明中,对所有参数的类型和变量名的声明形式上必须保持一致。推荐使用仅对参数类型进行声明的形式。
例如:
/**********
* 禁止参数的声明形式上不一致
**********/
float static_p (unsigned int, unsigned short p_2);
基于加强代码可读性、避免人为失误的目的,过程体必须用大括号括起来。
基于加强代码可读性、避免人为失误的目的,循环体必须用大括号括起来。例如:
/**********
* 循环体必须用大括号括起来
*********/
int static_p(int p_1)
{
int j=10;
int k=0;
/*...*/
for (k=0; k<10; k=k+1) j--;
return;
}
基于加强代码可读性、避免人为失误的目的,then/else中的语句必须用大括号括起来。
例如:
/**********
*then/else中的语句必须用大括号括起来
*********/
int static_p (int p_1, int p_2)
{
int i=;
int j=2;
/*...*/
if (p_1>0) {
i=i-1;
} else
i=i+1;
if (p_2>0) {
j=j+p_2;
} else if (p_2<0){
j-j-p_2;
}else{
j=i;
}
return i;
}
在含有逻辑操作符的表达式中使用括号可使运算顺序变得清晰,且不容易出错,因此逻辑表达式的连接必须使用括号。
例如:
/**********
* 逻辑表达式的连接必须使用括号
*********/
void static_p (void)
{
bool flag=true;
unsigned int y=Ou, x=Ou, z=lu;
/*...*/
if (x<0 || z+y!=0&&!flag)
{
flag=false;
}
}
头文件应放在文件开始的地方,应在任何可执行代码之前。
例如:
/**********
* 禁止在头文件前有可执行代码
*********/
void static_p (void)
{
#include " myfile.h"
/*...*/
}
宏体内使用的参数必须用括号括起来。
例如:
/**********
* 宏参数必须用括号括起来
*********/
#define static_p(x) x>=0?x:-x
void test_p (void)
{
unsigned int result;
int a=6, b=5;
/*...*/
result=static_p(a-b);
result=static_p(a)+1;
/*...*/
}
该准则是为了确保所有插入的代码是有界面定义的纯过程。
例如:
/**********
* 恢入汇编程序的过程必须是纯汇编程序
*********/
void static_p (void)
{
unsigned int x;
x=0u;
_asm
{
mov eax, x
}
}
“‘”
、“\”
和“/*”
等字符头文件名使用“‘”
、“\”
和“/*”
等字符会带来隐含的冲突,因此头文件名禁止使用“‘”
、“\”
和“/*”
等字符。
“\”
,字符串的终止必须使用“\0”
只用“\”
并不能控制字符串的终止,应该用“\0”
控制字符串的终止。
例如:
/**********
* 禁止字符串中单独使用“\”,字符串的终止必须使用“\0”
*********/
void static_p (void)
{
unsigned char* str=(unsigned char*) " string\
literal";
/*...*/
}
int main(void)
或 int main(int,char* [])
的形式main须定义为int main(void)
或 int main(int,char* [])
的形式的形式,这有助于错误的确定和参数的输入。
例如:
/**********
* main须定义为 int main(void)或int main(int, char* [])的形式
*********/
void static_p (void)
{
/*...*/
}
条件判别成立时相应分支中无任何执行语句,可能是由于疏忽而遗漏掉了,或是有意避免布尔表达式不成立时的情况。为了防止由于疏忽造成的遗漏,因此禁止条件判别成立时相应分支无执行语句。
该准则的违背通常为下面几种形式:
a) if(...)else
b) if(...) { } else
c) if(...) {; } else
例如:
/**********
* 禁止条件判别成立时相应分支无执行语句
*********/
void static_p (void)
{
unsigned int value_x=lu;
/*...*/
if (value_x==Ou);
/*...*/
if (value_x==0u) {
#if FALSE
value_x=value_x+lu;
#endif
}
/*...*/
if (value_x==0u) {;}
}
在if...else if语句中为了表明已经考虑了所有情况,必须使用else分支。
例如:
/**********
* 在if...else if语句中必须使用else分支
*********/
void static_p (void)
{
unsigned int x=2u;
/*...*/
if (x= =2u) {
/*...*/
} else if (x= =3u) {
/*...*/
}
}
else分支中无可执行语句或是由于代码不完整造成的,或是有意表明else对应的可能性已经考虑到,了。为了防止残留不完整的代码,因此禁止条件判别的else分支无可执行语句。
该准则的违背通常为下面几种形式:
a) else;
b) else { }
c) else {; }
例如:
/**********
* 禁止条件判别的else分支无可执行语句
*********/
void static_p (void)
{
unsigned int name_x=lu;
/*...*/
if (name_x= =0u)
{/*...*/}
else;
/*...*/
if (name_x= =0u)
{/*...*/}
else
{
#if FALSE
name_x=name_x+lu;
#endif
}
/*...*/
if (name_x= =0u)
{/*...*/}
else
{;}
}
如果switch语句中缺省了default语句,当所有的case语句的表达式值都不匹配时,则会跳转到整个switch语句后的下一个语句执行。强制default语句的使用体现出已考虑了各种情况的编程思想。
例如:
/**********
* 在switch语句中必须有default语句
*********/
void static_p (int p_1)
{
int i=0, j=0;
/*...*/
switch (p_1)
{
case 0:
j=0;
break;
case 1:
j=i;
break;
}
/*...*/
}
空switch语句不具备任何实际的操作内容,因此禁止使用空switch语句。
例如:
/**********
* 禁止使用空switch语句
*********/
void static_p (int p_1)
{
int i=p_l;
switch (i)
{
}
}
如果switch语句中只包含default语句,则该switch语句的使用无任何实际价值,因此禁止switch语句中只包含default语句。
例如:
/**********
* 禁止switch 语句中只包含default语句
*********/
void static_p (int p_1)
{
int i=p_l;
switch (i)
{
default;
i++;
}
}
如果某个case语句最后的break被省略,在执行完该case语句后,系统会继续执行下一个case语句。case语句不是有break终止,有可能是编程者的粗心大意,也有可能是编程者的特意使用。为了避免编程者的粗心大意,因此禁止switch的case语句不是由break终止。
例如:
/**********
* 禁止switch的case语句不是由break终止
*********/
void static_p (int p_1)
{
int i=0, j=0;
switch (p_1)
{
case 0:
j=0;
case 1:
j=i;
break;
default:
i=j+1;
}
/*...*/
}
如果某个case语句中无任何可执行语句,则它将共享后面case语句中的执行语句。这种情况或是由于代码不完整造成的,或是编程者特意设计的。为了防止残留不完整的代码,因此禁止switch的case语句中无任何可执行语句。
例如:
/**********
* 禁止switch的case语句中无任何可执行语句
*********/
int static_p (int p_1)
{
int i=0, j=0;
/*...*/
switch (p_1)
{
case 0:
j=0;
break;
case 1:
case 2:
j=i;
break;
default:
i=j+1;
}
return i+j;
}
将参数指针赋值给过程指针会导致不可预料的结果,因此禁止将参数指针赋值给过程指针。
例如:
/**********
* 禁止将参数指针赋值给过程指针
*********/
unsigned int *static_p (unsigned int *pl_ptr)
{
static unsigned int w=10u;
/*...*/
pl_ptr=&w;
/*...*/
return &w;
}
对指针进行控制是很困难的,当指针的指针超过两级时,使用起来更是具有风险,因此禁止指针的指针超过两级。
例如:
/**********
* 禁止指针的指针超过两级
*********/
void static_p (void)
{
unsigned int array[10]={0};
unsigned int *pl_ptr, **p2_ptr;
unsigned int **p3_ptr;
unsigned int w;
pl_ptr=array;
p2_ptr=&pl_ptr;
p3_ptr=&p2_ptr;
w=**p3_ptr;
}
使用过程指针是具有较大风险的,因此禁止将过程声明为指针类型。
例如:
void foo (unsigned int p_1, unsigned short p_2)
{/*...*/};
/**********
* 禁止将过程声明为指针类型
*********/
void static_p (void)
{
void (*proc_pointer) (unsigned int, unsigned short) =foo;
proc_pointer (lu, 1);
/*...*/
}
直接从过程中跳出破坏了程序的结构化,因此禁止直接从过程中跳出。
例如:
#include <set jmp.h>
/**********
* 禁止直接从过程中跳出
*********/
static void static_p (jmp_buf mark, unsigned int val)
{
longjmp (mark, val);
}
使用goto语句是不好的编程习惯, goto语句破坏了程序的结构化,因此禁止使用goto语句。
例如:
/**********
* 禁止使用goto 语句
*********/
void static_p (void)
{
int jump_flag=0;
/*...*/
start:
jump_flag++;
if (jump_flag<10) {
goto start;
}
}
在非赋值表达式中出现赋值操作符,可能是由于将“==”误写为“=”造成的,这会引起无法预料的后果,因此禁止在非赋值表达式中出现赋值操作符。
例如:
/**********
* 禁止在非赋值表达式中出现赋值操作符
*********/
void static_p (void)
{
unsigned int z=0u, x=0u;
bool flag=true;
/*...*/
if (flag=false) {
z=x-lu;
}
/*...*/
}
该准则的违背通常是下标超出了数组所指定的范围。
例如:
/**********
* 数组的使用必须保证不会出现越界
*********/
void static_p (void)
{
unsigned int a[4] /
/*...*/
a[5]=1;
/*...*/
}
对有符号类型进行移位运算会导致不可预料的后果。
例如:
/**********
* 禁止对有符号类型进行移位运算
*********/
void static_p (void)
{
int b=1;
/*...*/
b>>=1;
}
一些编译器不检查移位运算是否超出机器字长。
例如:
/**********
* 对变量进行移位运算必须保证不会产生溢出
*********/
void static_p (void)
{
unsigned int x=0u;
unsigned int y=2u;
/*...*/
x=y<<34;
}
给无符号变量赋负值会导致不可预料的结果,因此禁止给无符号变量赋负值。
例如:
/**********
* 禁止给无符号变量赋负值
*********/
void static_p (void)
{
unsigned int x=1u;
unsigned int y=2u;
/*...*/
y=-x;
}
有符号类型只给一位的长度是没有意义的,因此有符号类型的位长度必须大于等于两位。
例如:
/**********
* 有符号类型的位长度必须大于等于两位
*********/
struct static_p{int x:1;};
void dummy (void)
{
/*...*/
}
位不能定义为有符号或无符号整数之外的其它类型。
例如:
/**********
* 位的定义必须是有符号整数或无符号整数
*********/
struct static_p {unsigned char x:1; };
void dummy (void)
{
/*...*/
}
给变量赋的值与变量的类型不一致会导致数值有效位的损失。
例如:
/**********
* 禁止给变量赋的值与变量的类型不一致
*********/
void static_p (void)
{
unsigned int d;
d=2.0; /* Requires explicit assignment of 2u */
/*...*/
}
赋值类型不匹配会导致数值有效位的损失。
例如:
/**********
* 赋值类型必须匹配
*********/
void static_p (void)
{
float fl=2.0f;
double dbl=3.0;
/*...*/
fl=dbl;
}
数组下标表示数组元素的序号,所以数组下标必须是整型数。
例如:
#define ArraySize 3.0f
/**********
* 数组下标必须是整型数
*********/
void static_p (void)
{
unsigned int fl_arr[ArraySize]={0, 1, 2};
}
对常数值做逻辑非的运算会使得逻辑判别思路混乱。
例如:
/**********
* 禁止对常数值做逻辑非的运算
*********/
void static_p (void)
{
bool flag=false;
if(flag==!1)
{
/*...*/
}
}
位运算对有符号的数是很危险的,因为符号位会被错误地改变。
例如:
/**********
* 禁止对有符号类型使用位运算
*********/
void static_p (void)
{
int b=1;
/*...*/
b=b | 1;
/*...*/
}
枚举类型只能用于与其它枚举类型进行比较,禁止对枚举类型的越限使用。
例如:
/**********
* 禁止对枚举类型的越限使用
*********/
void static_p (void)
{
enum E_type (Enum1, Enum2, Enum3);
unsigned int ui;
ui=Enum1;
/*...*/
}
变量在运算过程应确保不会发生超界的数据溢出,对安全关键变量必须要仔细进行值域检查。
在逻辑表达式中使用赋值操作符,可能是由于将“==”误写为“=”造成的,这会引起无法预料的后果,因此禁止在逻辑表达式中使用赋值操作符。
例如:
/**********
* 禁止在逻辑表达式中使用赋值操作符
*********/
void static_p (void)
{
bool flag=false;
if (flag=false) /* This condition should be (flag= =false)*/
{
/*...*/
}
}
这种用法是一种不好的编程习惯,因为赋值被条件化了,原期望的赋值未必能被执行,因此禁止赋值操作符与“&&”或“||”连用。
例如:
/**********
* 禁止赋值操作符与“&&”或“||”连用
*********/
void static_p (void)
{
bool flag=false;
unsigned int y=0u, x=0u;
/*...*/
if (flag && ((x=y) ==0)){
/*...*/
}
}
这种情况的出现通常是用错了操作符号,例如把“||”误写为“!”。
例如:
/**********
* 禁止位操作符带有布尔型的操作数
**********/
void static_p (void)
{
unsigned int x=lu;
bool flag=false;
/*...*/
if((flag | (x!=0)) ==false) {
/*...*/
}
}
这种情况的出现通常是用错了操作符号,例如把“&&”误写为“&”。
例如:
/**********
* 禁止位操作符作用于布尔值
**********/
void static_p (void)
{
unsigned int y=2u;
bool flag=false;
flag=flag & (y==2u);
}
一些编译连接器忽略实参与形参的个数检查。为了防止实参与形参匹配的错误,强制要求实参与形参的个数必须一致。
例如:
unsigned int test_p (unsigned int p_1, unsigned short p_2)
{
unsigned int result=0u;
/*...*/
result=p_1+p_2;
return result;
}
/**********
* 实参与形参的个数必须一致
**********/
void static_p (unsigned int p_1, unsigned short p_2)
{
test_p(lu, 2, 3);
}
主过程所在文件中如果有未被该文件中任何过程调用的子过程,那么这个子过程有可能被其它文件中的过程所调用,应该把这个子过程移到有过程调用它的那个文件中去。
例如:
/**********
* 主过程所在文件中禁止有未被该文件中任何过程调用的子过程
**********/
unsigned int static_p (unsigned int p)
{
unsigned int x =lu;
/*....*/
x=x+p;
return x;
}
int main (void)
{
/*...*/
return(0);
}
如果一个过程被声明为static的类型,那么它的作用域为所在文件。若它在所在文件中没被调用,就应该把它去掉。
例如:
static bool static_p (unsigned int);
/**********
* static类型的过程在所在文件中必须被调用
**********/
static bool static_p (unsigned int p_1)
{
bool ret=false;
unsigned int i=p_1+lu;
/*...*/
if (j==0){
ret=true;
}
return ret;
}
void main (void)
{
/*...*/
}
由于某些原因,有许多被禁止使用的一些特殊项,如:
a)库中的过程或函数;
b)库文件;
c)特定的名称。
在一些文件中对extern的使用有严格限制,必须保证在不能使用extern的文件中禁止使用extern。
例如:
/**********
* 在不能使用extem的文件中禁止使用extern
**********/
/* any extern to be forbidded */
extern unsigned int undef_global;
void static_p (void)
{
undef_global=lu;
}
如果同一个表达式中调用多个相关函数,可能会因执行的顺序不同而产生不同的结果,因此禁止同一个表达式中调用多个相关函数。
例如:
unsigned int exp_1 (unsigned int *p_1)
{
unsigned int x=*p_l;
(*p_1) =x*x;
return (x);
}
unsigned int exp_2 (unsigned int *p_1)
{
unsigned int x=*p_1;
(*p_1)=(x %2);
return (x);
}
/**********
* 禁止同一个表达式中调用多个相关函数
**********/
void static_p (void)
{
unsigned int y=3u, x=0u;
x=exp_i (&y) +exp_2 (&y);
}
返问类型说明为void的过程用在表达式中使用是危险的,因此禁止void类型的过程用在表达式中使用。
例如:
void foo (void)
{
/*...*/
}
/**********
* 禁止void类型的过程用在表达式中使用
**********/
void static_p (void)
{
char x;
x=(char) foo ();
}
传递void类型的参数会导致不可预料的结果,因此禁止:void类型的变量作为参数进行传递。
例如:
void void_para_func (void *p_1)
{
/*...*/
}
/**********
* 禁止void类型的变量作为参数进行传递
**********/
void static_p (unsigned int p_1, unsigned short p_2)
{
int y=0;
void *v_ptr=&y;
y=(int) (p_1+p_2);
void_para_func (v_ptr);
}
为了严格的参数类型匹配检查,因此禁止实参和形参类型不一致。
例如:
void foo (unsigned short p_1, unsigned short p_2)
{
/*...*/
}
/**********
* 禁止实参和形参类型不一致
**********/
void static_p (unsigned int p_1, unsigned short p_2)
{
foo (p_1, p_2);
/*...*/
}
为了严格的函数类型匹配检查,因此函数和原型参数类型必须一致。
例如:
bool static_103 (float up_1);
/**********
*函数和原型参数类型必须一致
**********/
bool static_p (unsigned int up_1)
{
bool ret=false;
/*...*/
return ret;
}
小写字母“1”很容易与数字“1”混浠,大写字母“O”很容易与数字“0”混淆,因此禁止单独使用小写字母“1”或大写字母“O”作为变量名。
例如:
/**********
* 禁止单独使用小写字母“1”或大写字母“O”作为变量名
**********/
void static_p (void)
{
int l=1, O=0;
/*...*/
1=0;
O=1;
}
三字母词的使用使得程序难于阅读,容易出现编程失误。
例如:
/**********
* 禁止三字母词的使用
**********/
void static_p (void)
{
??</*??(在这里代替(*/
/*...*/
}
由于八进制数是以0开始的,容易与十进制的数混泽,所以使用的八进制数必须加以注释。
例如:
/**********
* 使用的八进制数必须加以注释
**********/
void static_p (void)
{
unsigned int i;
i=(unsigned int) 076;
/*...*/
}
一个函数应该有一个返回语句,否则函数会返回一个随机数,这个随机数通常是堆栈顶端值。
例如:
/**********
* 函数必须有返回语句
**********/
unsigned int static_p (unsigned int p_1, unsigned short p_2)
{
unsigned int y=p_1;
/* Not returning a value */
}
如果过程返同类型为void,则该过程的设计本身就是无返回类型值的,因此禁止void类型的过程中的return语句带有返回值。
例如:
/**********
* 禁止void类型的过程中的return 语句带有返回值
**********/
void static_p(unsigned int p_1, unsigned int p_2)
{
unsigned int result;
/*...*/
result=p_1+p_2;
return result;
}
有返回值的函数中如果只有return语句而无具体的指定值,则此时将返回一个随机数。
例如:
/**********
* 有返问值的函数中return必须带有返回值
**********/
unsigned int static_p (unsigned int p_1, unsigned short p_2)
{
/*...*/
return;
}
既然依据设计定义了函数的返回类型,则函数的实际返回类型必须与定义的返回类型相一致。
例如:
/**********
* 函数返回类型必须一致
**********/
unsigned int static_p (unsigned int par_1)
{
switch (par_1) {
case 0:
return (-1);
break;
case 1:
return (1u);
break;
case 2:
return (1L);
break;
case 3:
return (1.0f);
break;
default:
break;
}
}
既然依据设计声明了原型的返回类型,则函数的返回类型必须与原型的返回类型相一致。
例如:
float static_102 (unsigned int, unsigned short);
/**********
* 函数和原型返回类型必须一致
**********/
int static_p (unsigned int p_1, unsigned short p_2)
{
int result=0;
/*...*/
return result;
}
嵌套注释是否通过依赖于具体的编译器,同时嵌套注释也影响了程序的可读性,所以禁止使用嵌套的注释。
例如:
/**********
* 禁止使用恢套的注释
**********/
void static_p (void)
{
/* This is the Outer Comment
/* This is the Inner Comment
*/
}
有许多类型不适合用于循环变量,尤其是实型变量。
例如:
/**********
* 禁止使用不合适的循环变量类型
**********/
void static_p (void)
{
float f=0.0f;
/*...*/
for (f=0.0f; f<10.0f; f=f+1.0f){
/*...*/
}
}
循环变量应该定义在最小的范围内,即循环变量的作用域应最小,所以循环变量必须是局部声明的。
例如:
unsigned int global_f=0u:
/**********
* 循环变量必须是局部声明的
**********/
int loop_standards (int p_1)
{
int j=10;
/*...*/
for (global_f=0; global_f<10; global_f=global_f+1) {
j--;
}
return j;
}
强制将其它类型转换为指针类型是很危险的,因此禁止对指针变量使用强制类型转换赋值。
例如:
/**********
* 禁止对指针变量使用强制类型转换赋值
**********/
void static_p (void)
{
unsigned short s=0;
unsigned int *pl_ptr;
pl_ptr=(unsigned int *)s;
/*...*/
}
枚举类型的初始化只有两种形式是安全的。一是初始化所有的元素,二是只初始化第一个元素。
例如:
/**********
* 枚举元素的初始化必须完整
**********/
void static_p(void)
{
enum E_type {numl, num2=2, num3};
/*...*/
}
结构体变量的初值类型必须与结构体变量的定义类型一致。
例如:
struct s_type_a{int xs; float fs; };
/**********
* 结构体变量初始化的类型必须一致
**********/
void static_p (void)
{
struct s_type a sta={3.14f. 0.0f};
/*...*/
}
通常是编程者疏忽了结构中的结构变量的嵌套层次关系,在对结构体变量初始化时必须要保持与定义的嵌套结构相一致。
例如:
struct pixel (unsigned int colour: struct {unsigned int x, y:} coords;};
/**********
* 结构体变量初始化的长套结构必须与定义的相一致
**********/
void static_p (void)
{
unsigned int xs=0u;
unsigned int ys=0u;
struct pixel spot= {u, xs, ys};
/*...*/
}
在使用变量前应确保变量已被赋值。例如:
unsigned int x;
unsigned int y;
y=x;
其中对变量x的使用,在使用前未被赋值。
如果变量是在某些条件前提下进行的赋值,在条件结束后使用该变量,则同样是违背该条准则。
对实数类型的量做是否相等的比较是很危险的,因为实数类型的量完全相等的几率是很小的。
例如:
/**********
* 禁止对实数类型的量做足否相等的比较
**********/
void static_p (void)
{
float fl, f2;
fl=1.01f;
f2=2.01f;
/*...*/
if(fl= =f2){
/*...*/
}
if (fl==0.0f) {
fl=fl+0.01f;
}
}
逻辑判别的表达式应是逻辑表达式,逻辑表达式才真正体现了逻辑的判别。通常该准则的违背是在应使用逻辑表达式的地方使用了整数表达式。
例如:
/**********
* 禁止逻辑判别的表达式不是逻辑表达式
**********/
void static_p (void)
{
unsigned int x=0u;
if(x){
/*...*/
}
}
因为逻辑表达式只有真和假两种情况,当需要对逻辑表达式判别时,应使用if then else语句,而不应是switch语句。
例如:
/**********
* switch语句中的表达式禁止是逻辑表达式
**********/
void static_p (void)
{
bool flag=false;
/*...*/
switch (flag) {
case true:
/*...*/
break;
case false:
/*...*/
break;
default:
break;
}
}
枚举类型中的元素名应保持唯一性。该准则的违背通常表现在,枚举中元素名与已有的全局变量名同名。
例如:
unsigned int duplicate=0u;
/**********
* 禁止枚举类型中的元素名与已有的变量名同名
**********/
void static_p (void)
{
enum Name_type {el, duplicate} EnumVar;
EnumVar=el;
/*...*/
}
C语言编译器是允许局部变量与全局变量同名,但局部变量的作用域只限制在声明的模块内部。为避免本意是需要对全局变量更新,但由于存在同名的局部变量,导致全局变量未得到实际有效的更新,因此禁止局部变量与全局变量同名。
例如:
unsigned int Fire_Command:
/**********
* 禁止局部变量与全局变量同名
**********/
void static_p (void)
{
unsigned int Fire_Command=2u;
……
}
形参名与全局变量名同名使程序的可读性降低,且容易出现编程失误,因此禁止形参名与全局变量名同名。
例如:
/*--Global Declarations --*/
unsigned int global_int=0;
/**********
* 禁止形参名与全局变量名同名
**********/
void static_p (unsigned int *global_int)
{
/*...*/
}
形参名与类型或标识符同名使程序的可读性降低,且容易出现编程失误,因此禁止形参名与类型或标识符同名。
例如:
typedef unsigned int DUPLICATE;
/**********
* 禁止形参名与类型或标识符同名
**********/
void static_p (unsigned int DUPLICATE)
{
/*...*/
}
块结构允许在内部块中重定义已有的变量名,但这是不好的编程习惯,且容易出现编程失误,因此禁止在内部块中重定义已有的变量名。
例如:
/**********
* 禁止在内部块中重定义已有的变量名
**********/
void static_p (unsigned int p_1)
{
unsigned int static_p;
bool c_1=false;
/*...*/
if(c_1){
unsigned int static_p=1u;
/*...*/
static_p=static_p+lu;
} else{
static_p=p_1;
}
/*...*/
}
volatile类型变量的值可以被随意地改变,因此只在简单的表达式中使用它才是安全的,而在复杂表达式中禁止使用volatile类型的变量。
例如:
/**********
*禁止复杂表达式中使用volatile类型的变量
**********/
void static_p (void)
{
unsigned int y=0u; x=0u, z=1u;
volatile unsigned int v=1u;
/*...*/
x=v+z/v*y;
/*...*/
}
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。