目录
1.bool变量与“0值”进行比较
1.1 bool类型介绍
问题:C语言有没有bool类型?
一:c89或c90没有_bool类型//c99引入了_Bool类型
二:(细谈)c99之前,主要是c90是没有的,目前大部分书,都是认为没有的。因为书,一般都要落后于行业。 但是c99引入了_Bool类型(你没有看错,_Bool就是一个类型,不过在新增头文件stdbool.h中,被重新用宏写成了 bool,为了保证C/C++兼容性)。
C语言中我们都清楚0表示假,非0表示真
可bool类型用的是true和false来表示真假
测试代码一:(此代码用VS2013进行编译的,所以有#include <windows.h>和system("pause");)
#include <stdio.h>
#include <stdbool.h> //没有这个头文件会报错,使用新特性一定要加上
#include <windows.h>
int main()
{
bool ret = false;
ret = true;
printf("%d\n", sizeof(ret)); //vs2013 和 Linux中都是1
system("pause");
return 0;
}
//查看源码:
#define bool _Bool //c99中是一个关键字哦,后续可以使用bool
#define false 0 //假
#define true 1 //真
PS:理论上,表示真假,需要一个bit就够了,不过这个问题,还是要取决于编译器的理解。vs2013中认为是1个字节。
but!!
//测试代码2:
#include <stdio.h>
#include <windows.h>
int main()
{
//在vs中,光标选中BOOL,单击右键,可以看到转到定义,就能看到BOOL是什么
BOOL ret = FALSE;
ret = TRUE;
printf("%d\n", sizeof(ret)); //输出结果是4,因为在源代码中,是这么定义的:typedef int BOOL;
system("pause");
return 0;
}
我们发现,竟然也能编过。。。什么鬼??
这都是Microsoft自己搞的一套BOOL值。在vs中转到BOOL对应的头文件,翻到最上面,就能看到微软的版权信息。 好了,该听谁的??
微软?强烈不推荐,大写的BOOL是微软的标准,跨平台性太差,可移植性较差,测试代码1在VS2013和Linux都可以编过,可代码2只能在VS2013中通过,Linux不行
所以,后面万一要用bool,强烈推荐C99标准的,摒弃微软
1.2 bool和0比较
通过代码解释:
#include <stdio.h>
#include <stdbool.h>
#include <windows.h>
int main()
{
int pass = 0; //0表示假,C90,我们习惯用int表示bool
//bool pass = false; //C99
if (pass == 0)
{
//理论上可行,但此时的pass是应该被当做bool看待的,==用来进行整数比较,不推荐
//TODO
}
if (pass == false)
{
//不推荐,尽管在C99中也可行
//TODO
}
if (pass)
{
//推荐
//TODO
}
//理论上可行,但此时的pass是应该被当做bool看待的,==用来进行整数比较,不推荐
//另外,非0为真,但是非0有多个,这里也不一定是完全正确的
if (pass != 1)
{
//TODO
}
if (pass != true)
{
//不推荐,尽管在C99中也可行
//TODO
}
if (!pass)
{
//推荐
//TODO
}
system("pause");
return 0;
}
2.浮点数与“0值”进行比较
2.1 浮点数之间的比较
精度损失:
浮点数在内存中存储,并不想我们想的,是完整存储的,在十进制转化成为二进制,是有可能有精度损失的。
注意这里的损失,不是一味的减少了,还有可能增多。浮点数本身存储的时候,在计算不尽的时候,会“四舍五入”或者其他策略
例如:
#include<stdio.h>
int main()
{
double d = 3.6;
printf("%.50f\n", 3.6);
return 0;
}
比较过程:(先看代码)
#include<stdio.h>
int main()
{
double x = 1.0;
double y = 0.1;
printf("%.50f\n", x - 0.9);
printf("%.50f\n", y);
if ((x - 0.9) == 0.1)
{
printf("you can see me!\n");
}
else
{
printf("oops!\n"); // oops!
}
return 0;
}
//浮点数在进行比较的时候绝对不能直接用==来进行比较!!!!
//浮点数本身有精度损失,进而导致各种结果可能有细微的差别。
解决方法:!!
法一:
伪代码:
if((x-y) > -精度 && (x-y) < 精度)
{
//TODO
}
正式代码:这里采用自定义EPSION来定义精度范围
#include<stdio.h>
#define EPSION 0.00000000001
int main()
{
double x = 1.0;
double y = 0.1;
if (((x - 0.9) - y) > -EPSION && ((x - 0.9) - y) < EPSION)
{
printf("you can see me!\n");
}
else
printf("oops!\n");
return 0;
}
法二:使用绝对值的方法解决这个问题
伪代码版本:
if(fabs(x-y) < 精度)
{
//fabs是浮点数求绝对值
//TODO
}
正式代码:
#include<stdio.h>
#include<math.h>
#include<float.h>
int main()
{
double x = 1.0;
double y = 0.1;
if (fabs((x - 0.9) - y) < DBL_EPSILON)
{
printf("you can see me!\n");
}
else
printf("oops!\n");
return 0;
}
2.2 浮点数和0比较
既然知道了浮点数之间的比较,那么将其中一个浮点数转换为0,就相当于是浮点数和0的比较
// 比较a和b,则需要按照下列进行比较
// fabs(a - b) < DBL_EPSILON)
// 比较a和0,可以将上述代码中的b转换为0,如下:
// fabs(a) < DBL_EPSILON)
// 说明只要满足上述代码要求,就可以说明a和0是相等的
#include<stdio.h>
#include<math.h>
#include<float.h>
int main()
{
double x = 0.00000000000000000000000000001;
//法一:
/*if (fabs(x) < DBL_EPSILON)
{
printf("you can see me! x==0.0\n");
}
else
{
printf("oops!\n");
}*/
//法二:
if ((x > -DBL_EPSILON) && (x < DBL_EPSILON))
{
printf("you can see me! x==0.0\n");
}
else
{
printf("oops!\n");
}
return 0;
}
/*问题:要不要带等号?
//不带: if ((x > -DBL_EPSILON) && (x < DBL_EPSILON))
// 带: if ((x >= -DBL_EPSILON) && (x <= DBL_EPSILON))
XXX_EPSILON是最小误差,但是:XXX_EPSILON+n不等于n的最小的正数。
不能带=
若fabs(x) == DBL_EPSILON
则double y + x != y;
且double y + DBL_EPSILON != y;
但是y + 0.0 == y;这才是正解
如果带了等号,就说明x本身,已经能够引起其他和他+-的数据的本身的变化了,这个不符合0的概念
所以以后不要写等号*/
3.指针变量和“0值”的比较
3.1 引言
看代码:
#include<stdio.h>
int main()
{
//类型是不同的
printf("%d\n", 0); //0
printf("%d\n", '\0'); //0
printf("%d\n", NULL); //0
int a = 0;
char* p = NULL;
//这里NULL的值是0是因为发生了强制类型转换
// 如何理解强制类型转换?
// 需要编写算法,或使用相关库函数
// "123456" -> int: 123456
// "123456" 7 字节 int 类型 4 字节 //真实转换
return 0;
}
// ******真实的转换会改变内存当中的数据 ******
// ******强制类型转化不改变内存中的数据,只改变对应的类型***
3.2 指针和0比较
#include<stdio.h>
int main()
{
int* p = NULL;
//if (p == NULL) 不推荐
//if (NULL == p) 推荐
return 0;
}