bool, float, 指针变量与“零值”比较的if语句
题目
请写出 bool
, float
, 指针变量
与“零值”比较的if
语句。
提示:这里“零值”可以是 0
, 0.0
, FALSE
或者 空指针
例如:int
类型变量n
与“零值”比较的if
语句为:
if (n == 0)
// ---- and ----
if (n != 0)
以此类推。
bool类型与其“零值”比较
根据布尔类型的语义,零值为“假”(记为FALSE
),任何非零值都是“真”(记为TRUE
)。TRUE
的值究竟是什么并没有统一的标准。例如Visual C++
将TRUE
定义为1
,而Visual Basic
则将TRUE
定义为-1
。
因此bool
类型在这里是不是一个长度为1的整型并不重要,重要的是if
语句的括号中需要填写的就是一个bool
表达式,而bool
类型本身就是一个bool
表达式,已经表达了与“零值”比较这个概念。因此bool
与其“零值”比较的if
语句应写为:
bool b;
if(b){
...
}
// ---- and ----
if(!b){
...
}
float类型与“零值”比较
float
类型对应的“零值”并不是0.0
,这是由于浮点类型会丢失精度。此外,float
类型不能用==
或者!=
进行比较,只能使用<=
和>=
构建一个排除其“零值”的区间进行比较,如图所示:
如仅分析理论,在c语言的float.h
或c++的cfloat
文件中,提供了一个FLT_EPSILON
常量。该常量为1.192092896e-07F
,表示1与大于的第一个(或最小)单精度浮点数之差,即理论最小正单精度浮点数。根据该常量,我们可以写出以下语句:
#include<float.h>
// c++ 为 #include<cfloat>
...
float a = 某浮点数;
...
// 为"零值"
if((a >= -FLT_EPSILON) && (a <= FLT_EPSILON)){
...
}
// ---- and ----
// 不为“零值”
if((a <= -FLT_EPSILON) || (a >= FLT_EPSILON)){
...
}
此外,double类型也有同样的极限常量,为DBL_EPSILON
,同样可从float.h
或cfloat
文件引入,在此不做赘述。
实际过程中,需要具体情况具体分析,还要考虑读数的测量误差等问题,而非简单用数学极限去排除“零值”。比如一个表示测量水桶水位的浮点读数,假设当水桶水空的时候,再往里面加水,此时我们如果用FLT_EPSILON
去比较就不太合理了。
指针变量与其“零值”比较
指针变量的零值是“空”(记为NULL
),在C语言和C++中,NULL
的定义并不相同。
在C语言中,习惯将NULL定义为void*
指针值0:
#define NULL (void*)0
在C++中,NULL却被明确定义为整常数0:
// wchar.h中定义NULL的源码
#ifndef NULL
#ifdef __cplusplus
#ifndef _WIN64
#define NULL 0
#else
#define NULL 0LL
#endif /* W64 */
#else
#define NULL ((void *)0)
#endif
#endif
在C++11以下的版本中,指针变量与其“零值”的比较,实质上就是指针变量与NULL
的比较,即:
char* c;
if(c == NULL){
...
}
// ---- and ----
if(c != NULL){
...
}
在C++11以上的版本中,由于nullptr
的引入,统一了C语言和C++的差异,因此最佳实践应该为:
char* c;
if(c == nullptr){
...
}
// ---- and ----
if(c != nullptr){
...
}