if语句是C/C++语言的常用逻辑表达语句,只要写过C/C++代码的开发人员,应该都或多或少写过对应的逻辑表达式,我们今天说的与零值的比较就基于这个话题进行展开。
一、背景
零值或者零值所代表的逻辑比较,是具体软件开发过程中进行业务处理的常用处理手段。经常碰到的零值比较,一般涉及整数、布尔值、指针、字符和浮点数等五种类型,看似简单的零值比较,稍微不注意的话,影响的后果可能不是一丁半点。所以,把简单的事情做好,也不是一件容易的事,任何时候都需要我们认真对待。
二、整数零值比较
整数的零值就是固定的0,没有其它额外的含义指示,所以它的比较相对也就简单的多,使用逻辑运算符“==”(等于)或者“!= ”(不等于)进行比较即可。
示例代码如下:
int value = 10;
if (0 == value) { // 整数零值比较
……
}
if (0 != value) { // 整数非零值比较
……
)
上述的代码看上去是不是非常简单?但是细心地你不知道是否注意到,示例代码中零值与变量的位置是否有什么不一样的地方?是的,零值在左边,变量在右边,而不是通常意义上的左边是变量,右边是零值。这样做的好处是为了避免类似下面代码的漏写符号而导致整个逻辑变化,而且这种问题还不容易发现:
if (value = 0) {
……
}
上述代码本来是逻辑比较,结果变成了赋值操作,然后再判断value值是否为0,最终永远都不会执行if里面的代码,整个逻辑已经发生翻天覆地的变化。
另外,也不建议整数的零值比较写成类似下面代码的形式:
if (value) {
……
}
if (!value) {
……
}
整数的零值比较变成了类似布尔值的零值比较,虽然最终的结果大同小异,但是从逻辑上来说,分别代表着不同类型值的比较,也隐含着良好的编码风格在里面。如果看过前面2025年9月3日发布的《编写优良风格的C/C++代码(一)》和2025年9月4日发布的《编写优良风格的C/C++代码(二)》文章,就会知道编码风格的重要性,这里不再重复。
三、布尔值零值比较
C语言没有布尔值,这是C++语言新增的产物。布尔值只有真(非零)和假(零)两种值,对应C++标准就是true表示真,false表示加,而对应Visual C++就变成了TRUE表示真,FALSE表示假。通过Visual C++的关联代码,我们可以看到TRUE和FALSE只是定义的宏,其实际代码如下:
#define FALSE 0
#define TRUE 1
但是TRUE和FALSE只是Visual C++的产物,对于跨平台而言具有局限性,所以推荐使用C++标准的true和false值,不管是Windows平台还是linux、国产化等平台,都可以一套代码打天下。其布尔值对应的零值比较示例代码如下:
bool value = true;
if (true == value) { // 布尔值非零值比较
……
}
if (false == value) { // 布尔值零值比较
……
}
当然,相比上面的代码,也有不少人推荐使用下面的零值比较代码:
if (value) { // 布尔值非零值比较
……
}
if (!value) { // 布尔值零值比较
……
}
就个人而言,就好比前面提到的之前写的关于代码风格的两篇文章,关键还是保持风格的统一。但是个人还是倾向于前者,因为从代码可以看出变量的类型,后者的话对于部分开发人员来说,处于一种无序的状态,布尔型可以如此表示,空指针也可以一样表示,数值零也可以,给人是似而非的感觉,不喜欢这种朦胧感。
四、指针零值比较
指针的零值是空指针,对应C语言就是NULL,对应C++虽然也可以用NULL表示空指针,但是对于C++11或者更高版本,推荐使用nullptr替代NULL,而NULL与nullptr的区别详细可查看2025年8月24日发布的《C与C++混用需要了解的空指针NULL与nullptr区别》文章内容。
指针零值的比较示例代码如下:
int *p1 = NULL;
int *p2 = nullptr;
if (NULL == p1) { // 指针零值比较
……
}
if (NULL != p1) { // 指针非零值比较
……
}
if (nullptr == p2) { // 指针零值比较
……
}
if (nullptr != p2) { // 指针非零值比较
……
}
为什么把NULL或者nullptr放在左边,而把变量放在右边,以及为什么不使用if (p1)、if (!p2)等类似的写法,在前面”整数零值比较”以及”布尔值零值比较”章节已经进行了相应考虑描述,这里不再重复。
五、字符零值比较
字符的零值是字符串的结束符\0,对应ASCII码为0,表示字符串的结束。相对来说,字符的零值比较方式固定,示例代码如下所示:
char c = ‘\0’;
if (‘\0’ == c) { // 字符零值比较
……
}
if (‘\0’ != c) { // 字符非零值比较
……
}
没有什么过多需要额外注意的,字符零值就是简单的结束符比较。
六、浮点数零值比较
相对来说,浮点数的零值比较才是这几种类型里面需要额外注意的。其它类型都是基于简单的相等与不相等的对比,浮点数就不是了。浮点数的零值是0.0,但是浮点数存储存在精度问题,不能直接使用相等(==)或着不相等(!=)运算符进行简单比较,而是需要判断浮点数的绝对值是否在一个允许的误差范围,示例代码如下所示:
static const double float_zero = 1e-9;
double value = 0.0;
if (fabs(value) < float_zero) { // 浮点数零值比较
……
}
其中float_zero常量定义浮点数的零值精度范围,小于该范围则认为是零值,其零值范围也可以依据实际需要进行调整,不是固定不变。
七、结语
小小的零值比较,其实也隐藏着不少的细节。特别是比较时的常量与变量代码的位置,往往可以看出代码风格、代码质量等关联的开发经验。所谓细节,不外如是。
八、联系
如果有任何疑问欢迎随时交流。学无止境,实事求是,每天进步一点点!