2.1. 操作符
33.&&和||右邊的操作數不應該含有邊緣影響(R)
int myfunc1(void);
int myfunc(void)
{
int is;
int x;
if( is && ( x ++ == 3)) /* 與規則衝突 */
if( is && (x == myfunc1())) /* 除非myfunc1不會產生邊緣影響 */
}
34.&&和||的邏輯操作數應該是主要表達式:單一的標識符,常數,或者帶有括號的表達式(R)
35.賦值操作不能用在返回布爾值的表達式中(R)
void foo()
{
int x;
int y;
x=y;
if ( x != 0) { // Ok
// ...
}
if ( ( x=y) != 0) { /*與規則衝突*/
}
if ( x=y ) { /*與規則衝突*/
}
}
36.邏輯操作不能與位循環操作混淆
我們知道,&&,||,!是邏輯操作符,而&,|,~是位操作符號,在邏輯表達式中,不允許使用非邏輯變量,例如:
int a, b;
if(a && b) { /* 與規則36衝突 */
}
37.位操作符不能用在有符號整型(signed int)變量上(R)
int goo() {
return 0;
}
void foo() {
int dVar = 1;
signed int sdVar = 0;
unsigned int udVar = 0u;
udVar = udVar & udVar; /* Ok */
udVar = udVar & dVar; /* 與規則37衝突 */
udVar = udVar & sdVar; /*與規則37衝突*/
udVar ^= udVar; /* Ok */
udVar ^= dVar; /*與規則37衝突 */
udVar ^= sdVar; /*與規則37衝突*/
udVar ^= goo(); /*與規則37衝突*/
unsigned int udVar2 = ~udVar; /* Ok */
unsigned int udVar3 = ~sdVar; /*與規則37衝突*/
}
38.移位操作符的右邊的操作數應該介於0和左手邊操作數位長度之間(R)
39.一元負(-)操作符不能作用於無符號的表達式(R)
例如
unsigned int a;
int b;
b = -a; /*與規則衝突*/
40.sizeof操作不能作用於具有邊緣影響的表達式上(A)
void myfunc() {
int a = 1;
sizeof(a); /*ok */
sizeof(a++); /* 與規則衝突 */
}
41.在確定的編譯器中進行整型相除的時侯,應該是可確定的,文檔化,並進行考慮(A)
這是由於在支持ISO C的編譯器中進行除法時可能出現兩種結果,例如,-5/3 有可能是 商-1餘-2,也有可能是商-2餘+1。因此在使用的時候要指明。
42.逗號運算符(,)不能使用,除非在for循環的控制表達式裏面(R)
void foo( int, int ); // Ok
void func() {
for (int i = 0; i >=0, i < 10; i++) { // ok
}
}
void func_one(int,int,int); // ok
void func_two(int,int); // ok
void bar()
{
int x,y,z;
func_one( x, y + 2, z ); // ok
func_two( (x--, y + 2), z ); /* 與規則42衝突 */
}
2.2. 轉換
43.隱式的轉換可能導致信息的丟失,因此不宜採用(R)
void myfunc() {
signed int a;
unsigned int b;
a = b; /* 與規則衝突 */
b = a; /* 與規則衝突 */
}
44.冗餘的顯示轉換不宜使用(A)
void myfunc()
{
char c = 1;
short s = 1;
double d = 1.0;
c = (char ) c; /* 與規則衝突 */
d = (double)(c * s + d); /* 與規則衝突 */
d = (double )(double)1/3; /* 與規則衝突 */
return;
}
45.指針與任何類型之間的轉換都不要使用(R)
{
unsigned long val = 0x00000000;
int *ptr = (int *ptr) val; /* 與規則衝突 */
}