在條件判斷的時候,我們經常會碰到與0值比較的情況,但是通常有許多人使用時采用不恰當的條件判斷。下面我們就詳細討論各種情況:
1. 布爾變量與零值的比較:
假設布爾變量的變量名為flag,則它和0值比較的條件判斷語句如下:
if(flag) //表示flag為真
if(!flag) //表示flag為假
原因:根據布爾類型的語義,0為假,任何非0都為真,也許有人會覺得那直接用下面這種寫法也行啊,
if(flag != 0) //表示flag為真
if(flag == 0) //表示flag為假
根據定義,似乎是對的,當然,在程序中也不會錯,但是我們會以為這是布爾類型和整型的比較,類型
不匹配!當然,還有下面一種方法。
if(flag == TRUE)//表示flag為真
if(flag == FALSE)//表示flag為假
不錯,對於許多語言,都有這兩個關鍵字,而且FALSE被定義為0,但是只要TRUE,大多數語言都將其定義
為1,而這卻沒有遵循布爾類型的定義(非零表示真),這樣的比較就會出現bug,比如flag=2時,就不會執行flag為真時的語句。
綜上所述,布爾類型的變量和0值比較是應采用以下寫法:
if(flag) //表示flag為真
if(!flag) //表示flag為假
2. 整型變量和零值的比較:
這中情況就很簡單了,就是下面的寫法:
if(flag != 0) //表示flag為真
if(flag == 0) //表示flag為假
3. 浮點數與零值的比較:
對於浮點數與零值的比較,就相對復雜一些。因為計算機表示浮點數都有一個精度限制。對於超出了精度限制的浮點數,計算機
會把它們的精度之外的小數部分截斷。因此,本來不相等的兩個浮點數在計算機中可能就變成相等的了。
float a = 2.111111112;
float a = 2.111111118;
理論上,這兩個數是不相等的,但是在32為機器上是相等的(原因:在32位機器上,float保留6為小數)。
所以,對於浮點數比較,是這樣規定的:如果兩個同符號浮點數之差絕對值銷毀或等於某一個可接受的誤差(即精度),就認為
它們是相等的,否則就是不相等的。至於精度應根據具體要求而定。而不要直接用“==”或“!=”對兩個浮點數進行比較
float sub = 0.0000001f;//自定義的精度
if(abs(a - b) <= sub);//表示a == b;
if(abs(a - b) > sub);//表示a != b;
而與零值的比較,當然就是下面的寫法了:
if(abs(a) <= sub);//表示a == 0;
if(abs(a) > sub);//表示a != 0;
注意:在實際的編程環境中,如果直接比較浮點數和另一個數(整型或浮點數)是否相等(==)或不等(!=),可能產生錯誤。
至於其結果,可能依賴於具體的編譯環境和平台,因為每一個編譯平台都有自己默認的精度,對於浮點數直接進行==和!=比較
采用的就是這個默認的精度,而不是按照內存中兩個僅有某個bit不同來判斷的。
4. 指針變量與零值的比較:
指針變量的零值是“空值”(即為NULL),即不指向任何對象。
所以指針變量與零值比較的標准if語句如下:
if(p == NULL) //p為空
if(p != NULL) //p不為空
雖然NULL的值與0相同,但是兩者意義不同。打開VC環境下的NULL定義:
[cpp]
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
也就是說NULL是定義的一個宏,這樣便可區分整型與0值的比較;
如果使用下面的寫法:
if(p != 0) //表示flag為NULL
if(p == 0) //表示flag為NULL
當然,這樣也不會錯,但是我們會誤以為p是整型變量。
雖然這都是一些很小的方面,但是程序中難以查找的bug往往就是出現在這些細節之處!