一、BOOL
1、C语言bool
详解
bool
是C语言中的一个关键字,用于声明布尔类型的变量。布尔类型只有两个可能的值:true
和false
。在C99标准之前,C语言并没有内置的布尔类型,人们通常使用int
类型,并用0
表示false
,非0
(通常是1
)表示true
。C99标准引入了bool
类型,以及头文件<stdbool.h>
,它定义了bool
、true
和false
。 2、bool
的用法和定义
要使用bool
类型,首先需要包含头文件<stdbool.h>
,
然后,你可以像声明其他类型的变量一样声明bool
类型的变量:
#include <stdbool.h>bool isHappy = true; bool isSad = false;
3、bool
的基本作用
bool
类型的主要作用是提供一种更直观、更易于理解的方式来表示逻辑值。在编写条件语句时,使用bool
类型的变量可以使代码更加清晰和易于理解。
4、bool
与其他类型的转换
在需要时,bool
类型的值可以隐式地转换为int
类型,其中false
转换为0
,true
转换为1
。但是,将int
类型转换为bool
类型时,0
会被转换为false
,任何非0
的值都会被转换为true
。
5、使用bool
的注意事项
不要将bool
类型的变量与整数类型混淆,尽管它们之间可以转换。在编写条件语句时,直接使用bool
类型的变量作为条件,而不要与true
或false
进行比较,例如if (isHappy)
而不是if (isHappy == true)
。在一些旧的C编译器或环境中,可能不支持bool
类型。在这种情况下,你可以使用int
类型并遵循相同的逻辑约定。 6、拓展:bool类型与其“零值”比较
在布尔逻辑的语义中,零值被视为“假”(FALSE),而任何非零值都被视为“真”(TRUE)。值得注意的是,TRUE的具体数值并没有统一的标准,它依赖于具体的编程语言或环境。例如,在Visual C++中,TRUE被定义为1,而在Visual Basic中,TRUE则被定义为-1。
重要的是要理解,bool
类型变量的本质是一个布尔表达式,用于表示与“零值”(即FALSE)的比较结果。因此,在if
语句中直接使用bool
类型的变量作为条件表达式,无需显式地与其“零值”进行比较。正确的if
语句用法如下:
bool b; // 假设b已被赋予某个值 if (b) { // 如果b为真(非零),则执行此处代码 ... } // 使用逻辑非操作符"!"来检查b是否为假(零值) if (!b) { // 如果b为假(零值),则执行此处代码 ... }
二、FLOAT
1、float的定义和用途
float关键字用于声明一个单精度浮点变量,它能够存储带有小数的数值,且数值范围相对较广。在C语言中,float类型通常占用4个字节(32位)的内存空间,其中1位用于符号位,8位用于指数位,而剩下的23位则用于尾数位。
2、float的基本使用
在C语言中,使用float关键字定义变量时,需要在变量名后加上“f”或“F”后缀,以明确表示这是一个float类型的常量。例如:
float a = 3.14f;//如果不加“f”或“F”后缀,编译器可能会将其视为double类型的常量,进而可能引发类型不匹配的警告或错误。
3、float的精度问题
float精度问题的根本原因在于计算机内部使用二进制来表示浮点数,而很多十进制小数无法完全用二进制精确表示。此外,float类型在存储时遵循IEEE 754标准,该标准将32位分为符号位(1位)、指数位(8位)和尾数位(23位),这种表示方式也限制了float的精度。
具体来说,尾数位用于表示浮点数的小数部分,但由于只有23位,因此只能精确表示一定范围内的数字。对于超出这个范围的数字,计算机将进行舍入操作,以找到最接近的可表示数字,从而导致精度损失。
4、精度问题的举例
1、0.1无法精确表示:
在十进制中,0.1是一个简单的数字,但在二进制中,它无法精确表示。当我们尝试将0.1存储为float类型时,计算机会将其转换为最接近的二进制分数,从而导致精度损失。例如:
float a = 0.1f; // 输出可能不是0.1,而是类似0.100000024的近似值
2、浮点数相加产生精度损失:
当我们将两个浮点数相加时,如果它们的小数部分无法精确表示,那么相加的结果也可能出现精度损失。例如:
float b = 0.2f; float c = a + b; // a为上面例子中定义的0.1f // c可能不是0.3,而是类似0.300000012的近似值
3、浮点数相加产生精度损失:
在进行循环或条件判断时,如果涉及到浮点数的比较,可能会因为精度问题而导致逻辑错误。例如,在判断两个浮点数是否相等时,由于精度损失,直接使用==
运算符往往不是最佳选择。
5、拓展: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去比较就不太合理了。
6、拓展:指针变量与其“零值”比较
指针变量的零值是“空”(记为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
的比较,而在C++11以上的版本中,由于nullptr
的引入,统一了C语言和C++的差异,如下:
//----------------C++ 11 以下--------------------char* c;if(c == NULL){ ...}// ---- and ----if(c != NULL){ ...}//----------------C++ 11 以上--------------------char* c;if(c == nullptr){ ...}// ---- and ----if(c != nullptr){ ...}