learn_C_deep_6 (布尔类型、布尔与“零值“、浮点型与“零值“、指针与“零值“的比较)

news2024/12/26 0:46:10

目录

语句和表达式的概念

if语句的多种语法结构

注释的便捷方法(环境vs)

if语句执行的过程

逻辑与&&   逻辑或||   运算关系的顺序

else的匹配原则

C语言有没有布尔类型

C99标准

sizeof(bool)的值为多少? 

_Bool原码

BOOL、TRUE、FALSE

sizeof(BOOL)的值为多少?

 BOOL与bool的区别

“零值”的比较

1.bool变量与“零值”比较

2.float、double变量与“零值”比较 - (这里以double为例) 

3.指针变量与"零值"比较


语句和表达式的概念

C语言中由一个分号;隔开的就是一条语句

printf("Hello!\n");

1+2;

C语言中,用各种操作符把变量连接起来,形成有意义的式子,就叫做表达式

1+2

if语句的多种语法结构

1.if语句

if(表达式)   
    语句;

2.if - else语句

if(表达式)    
    语句1;
else    
    语句2;

3.if - else if - else语句

//多分支    
if(表达式1)    
    语句1;
else if(表达式2)    
    语句2;
else    
    语句3;

注释的便捷方法(环境vs)

1.先按ctrl + k,再按ctrl + c

2.采用if(0)注释  --  不推荐

 同时我们还可以从上面得出一个结论:非0为真,0为假

if语句执行的过程

#include<stdio.h>
int main()
{
    int flag = 1;
    if (flag == 1)
        printf("hello world\n");
    return 0;
}

#include<stdio.h>
int isEmpty()
{
    printf("某种数据结构是否为空!\n");
    return 1;
}
int main()
{
    if ((isEmpty()) == 1)
        printf("yes\n");
    return 0;
}

1.先执行()中的表达式或者函数,得到真假结果
2.条件  判定功能
3.进行  分支功能

逻辑与&&   逻辑或||   运算关系的顺序

 总结:从左到右。

else的匹配原则

我们来看看下面的代码运行结果是啥?

相信我们很多人看到这里,由于x等于0,而不等于10,所以来到else打印hello yesterday!但其结果其实是什么也不打印,这里是因为else是与离他最近的if匹配的,由于x不等于10,所以里面的if-else语句没有执行,所以也就不会打印啦。我们来验证一下,在与if(x==0)后面加一个与之匹配的else语句。

 总结:以后写if_else时,建议带上{ },这样不仅不容易出粗,而且代码的可观性也比较好。

再来看一个代码

#include<stdio.h>
int main()
{
    int flag = 0;
    if (flag == 1);
    {
        printf("why you can see me?\n");
    }
    return 0;
}

C语言有没有布尔类型

        bool 类型只有两个值:true 和 false。上面我们写的if()语句中非0为真,0为假,是因为C语言没有提供bool类型,而且我们也知道if()只有是条件表达式为真我们才执行,所以我们一般都写if(1),而不写if(true)。

        当我们写if(true)或者定义bool类型的变量时,编译器也提示出来为定义的标识符,说明编译器不认识它们,证明C没有提供bool类型。

C99标准

         但其实C语言时是有bool类型的,只不过我们编译器目前采用的是C89 or C90的标准,而在C99中引入了_Bool类型,它是一个类型,不过在新增头文件stdbool.h中,被重新用宏写成了bool,为了保证C/C++兼容性。引入头文件stdbool.h,程序就没有错误了。

sizeof(bool)的值为多少? 

        在 C 语言标准中,bool 类型是由 stdbool.h 头文件引入的。bool 通常被定义为枚举类型,其中 false 的值为 0,true 的值为 1。因此,sizeof(bool) 的值在 C 语言标准中并没有规定。 一般情况下,sizeof(bool) 的大小应该是 1 字节,因为 bool 类型只需要存储一个二进制位(0 或 1)来表示 true 或 false。但是,具体的实现方式可能会因编译器和操作系统的不同而有所不同。

_Bool原码

BOOL、TRUE、FALSE

#include<stdio.h>
#include<windows.h>
int main()
{
    BOOL x = TRUE;
    x = FALSE;
}

 这里的BOOL实际上是一个重命名  -   typedef int BOOL; 这里我们可以证明一下

sizeof(BOOL)的值为多少?

 BOOL与bool的区别

我将BOOL转到定义后,发现开头有这么一串注释,这样他们的区别就很明显了。 

由上面的图片可以得到,BOOL是微软帮我们设计的,我们只能在微软的对应的开发工具才能使用BOOL,BOOL是微软的标准(不推荐,可移植性较差),而bool是通用的。

        总结:

                1.优先使用C90,就是我们之前用的非0为真,0为假。

                2.一定要使用bool类型,优先使用bool,不推荐BOOL(可移植性较差)。

“零值”的比较

        1.bool变量与“零值”比较

#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
    }

    写法三:
    //1.先执行()中的表达式,得到真假结果(true or false,逻辑结果) - 而这里的pass本身就是逻辑结果
    //2.条件  判定功能
    //3.进行  分支功能
    if (pass) { //推荐 - 直挂的反应出来了,flag是"bool"
        //TODO
    }
    system("pause");
    return 0;
}

结论:bool类型,直接判定,不用操作符进行和特定值比较。

        2.float、double变量与“零值”比较 - (这里以double为例) 

        我们接下来看这个代码,后面的注释是我们预测的输出。

#include <stdio.h>
int main()
{
    double x = 1.0;
    double y = 0.1;
    printf("%.50f\n", x - 0.9);//0.1
    printf("%.50f\n", y);//0.1
    if ((x - 0.9) == y) {
        printf("you can see me!\n");//输出you can see me!
    }
    else {
        printf("you can not see me!\n");
    }
    return 0;
}

但是当我们运行这个代码的时候,结果令我们大失所望呀。

 为什么呢?

这里我们将数值3.1打印50的精度,结果出现了一大堆意外的数字。

        这是因为浮点数在内存中存储,并不想我们想的,是完整存储的,在十进制转化成为二进制,是有可能有精度损失的。 注意这里的损失,不是一味的减少了,还有可能增多。浮点数本身存储的时候,在计算不尽的时候,会“四舍五入”或者其他策略。所以上面才会输出you can not see me!

那么两个浮点数该如何比较呢? -  应该进行范围精度比较

        在 C 语言中,由于浮点数的精度问题,不能直接使用等于号(==)判断两个浮点数是否相等。通常使用以下方法来比较两个浮点数的大小关系:

        1.定义一个比较精度值 EPS,例如 1e-6,代表可接受的最小误差范围

        2.判断两个数之差(绝对值)是否小于等于精度值 EPS;

了解fabs函数 

        

        在 C 语言中,fabs 函数属于 math.h 头文件,因此在使用该函数前需要先包含 math.h 头文件。该函数返回一个 double 类型的值,可以用于计算浮点数的绝对值。 

当我们去改进程序后,我么发现就可以比较两个浮点数了。

 两个精度定义

我们发现我们定义1e-6(也就是0.000001),可能有时候设置的误差范围比较大导致判断错误,那么我们一个具体怎么设置这个值呢,那么此时C语言就提供了两个精度:

#include //使用下面两个精度,需要包含该头文件

DBL_EPSILON //double 最小精度

FLT_EPSILON //float 最小精度

转到定义后

         XXX_EPSILON是最小误差,是:XXX_EPSILON+n不等于n的最小的正数。 EPSILON这个单词翻译过来是'ε'的意思,数学上,就是极小的正数 。

 请问我们这样写会有问题嘛? -  问题是:要不要相等

        XXX_EPSILON是最小误差,是:XXX_EPSILON+n不等于n的最小的正数。 XXX_EPSILON+n不等于n的最小的正数: 有很多数字+n都可以不等于n,但是XXX_EPSILON是最小的,但是, XXX_EPSILON依旧是引起不等的一员。 换句话说:fabs(x) <= DBL_EPSILON(确认x是否是0的逻辑),如果=,就说明x本身,已经能够引起其他和他+和-的数据本身的变化了,这个不符合0的概念。

 现在我们来回归主题:float、double变量与“零值”比较

#include <stdio.h>
#include <math.h>
#include <float.h>
#include <windows.h>
int main()
{
	double x = 0.00000000000000000000001;
	//if (fabs(x-0.0) < DBL_EPSILON){ //写法1
	//if (fabs(x) < DBL_EPSILON){ //写法2
	if (x > -DBL_EPSILON && x < DBL_EPSILON) { //写法3
		printf("you can see me!\n");
	}
	else {
		printf("you can not see me!\n");
	}
	system("pause");
	return 0;
}

        总结:在 C 语言中,由于浮点数在计算机中存储的方式和精度限制的原因,不能直接使用等于号来判断两个浮点数是否相等,也不能直接判断浮点数是否等于 0.0,如果我们要比较,就需要形成一个极小的精度EPS,然后将这个数与0.0的差值的绝对值进行比较,这样我们才能判断float、double变量与“零值”的比较。

3.指针变量与"零值"比较

        常识补充:对NULL, '\0', 0的整体理解

1.NULL、'\0'和0是C语言中常用的三个表示“0”的值。

 2.它们的类型是不同的。

 1. NULL:通常被定义为一个值为0的宏,表示指针不指向任何有效的内存地址。在大多数情况下,一个指针的值为NULL表示其未被初始化或者指向了无效的内存地址,NULL是'0'被强制转换成指针类型的值。

2. '\0':是一个字符常量,表示字符数组的结束符。在C语言中,字符串是由字符数组组成的,每个字符串的结尾都必须以'\0'字符作为结束标志,告诉程序字符串的长度。

3. 0:是整数常量的一种,表示数值0。在C语言中,用0来表示逻辑假,非0的值表示逻辑真。

4.强制类型转化的理解   


 总结:强制类型转化没有改变内存中的数据,只是改变了它的类型。

接下来看下面的写法哪个好

#include<stdio.h>
int main()
{
    int* p = NULL;
    if (p == 0)
    {
        //写法一
    }
    if (p)
    {
        //写法二
    }
    if (NULL == p)
    {
        //写法三
    }
    return 0;
}

写法一:尽管NULL的值和0一样,但是意义不同,写法一容易让人认为p是整形变量

写法二:让人认为p是bool变量

写法三:很容易让人认识到这是指针相关的判断

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/465161.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

音视频八股文(6)-- ffmpeg大体介绍和内存模型

播放器框架 常用音视频术语 • 容器&#xff0f;文件&#xff08;Conainer/File&#xff09;&#xff1a;即特定格式的多媒体文件&#xff0c; 比如mp4、flv、mkv等。 • 媒体流&#xff08;Stream&#xff09;&#xff1a;表示时间轴上的一段连续数据&#xff0c;如一 段声音…

dubbogo如何实现路由规则功能

dubbo-go中如何实现路由规则功能 路由规则&#xff08; routing rule &#xff09;是为了改变网络流量所经过的途径而修改路由信息的技术&#xff0c;主要通过改变路由属性&#xff08;包括可达性&#xff09;来实现。在发起一次 RPC 调用前起到过滤目标服务器地址的作用&…

Node第三方包 【node-xlsx】

文章目录 &#x1f31f;前言&#x1f31f;node-xlsx&#x1f31f;安装&#x1f31f;导出xlsx文件&#x1f31f;解析xlsx文件&#x1f31f;另外&#xff1a;其他支持读写Excel的Node.js模块有&#xff1a;&#x1f31f;直接导出excel文件 &#x1f31f;写在最后 &#x1f31f;前…

麒麟信安联合主办 | openEuler Developer Day 2023召开 openEuler全场景走向深入

【中国&#xff0c;上海&#xff0c;2023年4月21日】openEuler Developer Day 2023于4月20-21日在线上和线下同步举办。本次大会由开放原子开源基金会、中国软件行业协会、openEuler社区、边缘计算产业联盟共同主办&#xff0c;以“万涓汇流&#xff0c;奔涌向前”为主题&#…

【FTP工具】- Win10下免费的FTP服务器搭建 - FileZilla 的下载、安装、使用

目录 一、概述二、下载、安装2.1 下载2.2 安装 三、FileZilla服务器的使用3.1 连接服务器3.2 配置用户权限 四、在windows访问该Ftp服务器4.1 查看Ftp服务器IP4.2 访问Ftp服务器 一、概述 FileZilla服务器是一个免费的开源FTP和FTPS服务器&#xff0c;是根据GNU通用公共许可证条…

HTB靶机03-Shocker-WP

Shocker scan 2023-03-30 23:22 ┌──(xavier㉿xavier)-[~/Desktop/Inbox] └─$ sudo nmap -sSV -T4 -F 10.10.10.56 Starting Nmap 7.91 ( https://nmap.org ) at 2023-03-30 23:22 HKT Nmap scan report for 10.10.10.56 Host is up (0.40s latency). Not shown: 99 clos…

QT-day(2)-(常用类、信号与槽.....)

题目&#xff1a;编写一个登录功能的界面&#xff0c;在登录框项目中&#xff0c;将登陆按钮发射的tclicked信号&#xff0c;连接到自定义的槽函数中&#xff0c;在槽函数中&#xff0c;判断u界面输入的用户名是否为"admin ,密码是否为"123456如果验证成功&#xff0…

数据结构_时间复杂度/空间复杂度

目录 1. 数据结构在学什么 2. 数据结构的基本概念 3. 算法和算法评价 3.1 算法的基本概念 3.2 算法的特征 3.3 算法效率的度量 3.3.1 时间复杂度 3.3.2 空间复杂度 1. 数据结构在学什么 常言道&#xff1a;学以致用&#xff1b;学习完基本C语言程序&#xff0c;我们希…

AB数对 码蹄集

题目来源&#xff1a;码蹄集 题目描述&#xff1a; 大致思路&#xff1a; 遍历输入的n个整数&#xff0c;将每个数存入哈希表中&#xff0c;key为数值&#xff0c;value为该数出现的次数。 再次遍历这n个整数&#xff0c;对于每个数x&#xff0c;计算出x-C和xC的值&#xff0…

Go语言基础----Go语言简介

【原文链接】Go语言基础----Go语言简介 一、Go语言简介 Go语言&#xff0c;又称Golang&#xff0c;是Google公司的Robert Griesemer&#xff0c;Rob Pike 及 Ken Thompson开发的一种静态强类型、编译型的语言。Go语言语法和C语言接近&#xff0c;但是功能上内存安全&#xff…

【Python】lambda匿名函数

文章目录 前言lambda匿名函数的定义lambda匿名函数的使用使用lambda匿名函数写一个计算器总结 前言 在Python中,可以使用def 关键字定义函数,使用def定义的关键字是有名称的,在调用时可以重复使用.还有一种是使用lambda关键字进行函数的定义,这个方式定义的函数是匿名函数,只能…

51单片机(四)静态数码管和动态数码管显示

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

内存优化-比glibc更快的tcmalloc

TCMalloc 是 Google 开发的内存分配器&#xff0c;在不少项目中都有使用&#xff0c;例如在 Golang 中就使用了类似的算法进行内存分配。它具有现代化内存分配器的基本特征&#xff1a;对抗内存碎片、在多核处理器能够 scale。据称&#xff0c;它的内存分配速度是 glibc2.3 中实…

3d网上渲染平台是怎么渲图的_云渲染流程详解!

题主说的看到许多网友对‘’3d网上渲染平台是怎么渲图的‘’进行提问&#xff0c;瑞云渲染小编也提供自己的小小见解。针对3D网上渲染平台是指什么&#xff0c;实际应该是指云渲染农场。几十年来&#xff0c;随着计算机软硬件不断更迭&#xff0c;图形图像渲染的效果更加清晰、…

信号完整性分析基础知识之传输线和反射(二):阻性负载的反射,源端阻抗,弹跳图

传输线的端接需要考虑三种重要的特殊情况&#xff0c;每种情况中&#xff0c;传输线的特性阻抗均为50Ohm。信号将从源端在这条传输线上传播&#xff0c;并以特定的阻抗端接到达远端。 TIP:在时域中&#xff0c;信号对瞬时阻抗十分敏感&#xff0c;第二区域并不一定是一条传输线…

常见的链表的OJ题

在本次的博客当中&#xff0c;为了巩固关于链表技能的运用&#xff0c;我们先来看一些与链表有关的OJ题。 &#x1f335;反转链表 题目详情如下&#xff1a; 第一道题目从逻辑上看不难&#xff0c;我们只需要将链表进行拆分&#xff0c;将我们下一个节点进行一个类似于头插的操…

【Java 数据结构】Map和Set

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

35岁程序员被裁赔偿27万,公司又涨薪让我回去,前提是退还补偿金,能回吗?

在大多数人眼里&#xff0c;35岁似乎都是一道槛&#xff0c;互联网界一直都有着“程序员是吃青春饭”的说法&#xff0c;。 如果在35岁的时候被裁能获得27万的赔偿&#xff0c;公司又涨薪请你回去上班&#xff0c;你会怎么选&#xff1f; 最近&#xff0c;就有一位朋友在网上…

Linux安装miniconda3

下载Miniconda&#xff08;Python3版本&#xff09; 下载地址&#xff1a;https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh 安装Miniconda&#xff08;需要连网&#xff09; &#xff08;1&#xff09;将Miniconda3-latest-Linux-x86_64.sh上传到/o…

研读Rust圣经解析——Rust learn-14(面向对象)

研读Rust圣经解析——Rust learn-14&#xff08;面向对象&#xff09; Rust面向对象对象包含数据和行为封装继承多态 实现面向对象书写最外层逻辑userServiceUser Rust面向对象 在一些定义下&#xff0c;Rust 是面向对象的&#xff1b;在其他定义下&#xff0c;Rust 不是 对象…