【新书推荐】5.1 逻辑运算符

第五章 逻辑运算

       本章讲解逻辑运算符与逻辑运算,移位运算符与移位运算。

本章学习知识概要:

      逻辑运算符

      位运算符

5.1 逻辑运算符

本节必须掌握的知识点:

   示例十六

   代码分析

   汇编解析

5.1.1 示例十六

逻辑运算符包括逻辑与、逻辑或、逻辑非,如表5-1所示。

运算符

表达式

说明

&&逻辑与(并且)

条件1&&条件2

两个条件同时为真时,结果为真

||逻辑或(或)

条件1||条件2

两个条件有一个为真时,结果为真

!逻辑非(非)

!条件

条件为真时,结果为假

条件为假时,结果为真

                                 表5-1逻辑运算符

&&逻辑与

语法格式:expr1 && expr2;

当两个条件同时为真时,结果为真;否则为假。(在C语言中,非0为真,0为假)。

举例

1 && 2 //真&&真 -->结果为真

0 && 1 //假&&真 -->结果为假;当expr1为假时,将直接返回假,不会再计算expr2。

-1 && 0 //真&&假 -->结果为假

2>3 && 2 //假&&真 -->结果为假;当expr1为假时,将直接返回假,不会再计算expr2。

||逻辑或

语法格式:expr1 || expr2;

当两个条件有一个为真时,结果为真;否则为假。

举例

0 || 1  //假||真 -->结果为真;当expr1为假时,会继续计算expr2。

0 || 0  //假||假 -->结果为假;当expr1为假时,会继续计算expr2,expr2为假,则为假(两个条件都为假时,结果为假)。

!逻辑非

语法格式:!expr;当条件为真时,结果为假;当条件为假时,结果为真。

举例

!0         //假 -->结果为真

!1         //真 -->结果为假

!(1>2)     //假 -->结果为真

■德摩根定律

对各条件取非,然后将逻辑与变为逻辑或,逻辑或变为逻辑与,然后再取其否定,结果和原条件一样。

举例

x && y 和 !(! x || !y )相等

x || y 和 !(! x && !y )相等

【注意】单目运算符 ‘-’取补码,单目运算符‘~’ 符号取反。

示例代码十六

/*

   逻辑运算符

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int  x = 2,y = 4,z = 6;

    int num;

    printf("请输入一个整数:");

    scanf_s("%d", &num);

    if (y < num && z > num)

        printf("两个条件表达式同时为真时,逻辑与表达式为真!\n");

    if (x == num || y == num)

        printf("其中任意一个表达式为真时,逻辑或表达式为真!\n");

    if (!num)

        printf("num为零时,逻辑非表达式为真!\n");

   

    printf("num符号取反之后的值是%d\n", -num); //取num的补码

    printf("num补码的值是%d\n", ~num); //num符号取反   

    system("pause");

    return 0;

}

输出结果:

测试1

请输入一个整数:5

两个条件表达式同时为真时,逻辑与表达式为真!

num补码的值是-5

num符号取反之后的值是-6

测试2

其中任意一个表达式为真时,逻辑或表达式为真!

num补码的值是-4

num符号取反之后的值是-5

测试3

请输入一个整数:0

num为零时,逻辑非表达式为真!

num补码的值是0

num符号取反之后的值是-1

5.1.2 代码分析

    示例十六代码中定义了3个变量x,y,z。然后有用户输入一个整数值存入变量num中。接下来3个if条件语句中各包含一个逻辑运算符&&、||、!。如果if语句条件为真,使用printf函数输出结果。最后一个printf语句使用单目运算符 “-”符号取反,然后输出结果。

       当我们需要同时判断多个条件表达式时,我们可以使用“&&”逻辑与运算符或者“||”逻辑或运算符将多个条件表达式连接起来。

如果使用“&&”逻辑与运算符,连接的两个条件表达式同时为真时,结果为真;如果其中一个条件表达式为假,则结果为假。可以尽量选择条件为假可能性较大的表达式前置,如果前置条件表达式为假,则结果为假,后置的条件表达式就无需判断了,这样可以提高程序的运行效率。

如果使用“||”逻辑或运算符,连接的两个条件表达式只要其中一个为真,则结果为真;如果两个表达式全部为假,则结果为假。我们可以选择条件为真可能性较大的表达式前置,当前置表示为真时,结果为真,后置的表达式就无需判断了。

符号取反单目运算符 ‘~’。取补码运算符‘-’并不是逻辑运算符。

5.1.3 汇编解析

汇编代码

    ;C标准库头文件和导入库

include vcIO.inc

.data  

x   sdword 2      

y   sdword 4

z   sdword 6

num sdword  ?

.const 

szMsg1 db "请输入一个整数:",0

szMsg2 db "%d",0

szMsg3 db "两个条件表达式同时为真时,逻辑与表达式为真!",0dh,0ah,0

szMsg4 db "其中任意一个表达式为真时,逻辑或表达式为真!",0dh,0ah,0

szMsg5 db "num为零时,逻辑非表达式为真!",0dh,0ah,0

szMsg6 db "num符号取反之后的值是%d",0dh,0ah,0

szMsg7 db "num补码的值是%d",0dh,0ah,0

.code  

start:

    ;输入整数num

    invoke printf,offset szMsg1

    invoke scanf,offset szMsg2,ADDR num

    ;

    mov eax,num

    .if (y < eax) && (z > eax)

        invoke printf,offset szMsg3

    .endif

    mov eax,num

    .if (x == eax) || (y == eax)

        invoke printf,offset szMsg4

    .endif

    .if !num

        invoke printf,offset szMsg5

    .endif

    ;补码

    mov eax,num

    neg eax

    invoke printf,offset szMsg7,eax;输出结果

    ;符号位取反

    mov eax,num

    not eax     ;not取反指令,各位取反,符号位不变

    mov num,eax

    invoke printf,offset szMsg6,num;输出结果

    ;  

    invoke _getch  

    ret            

end start

    输出结果与C代码相同。

    上述汇编代码使用了.if\.else\.endif高级汇编决策伪指令,与C语言中的if/else语句基本相同。C语言中的‘-’运算符对应汇编中的neg求补指令。C语言中的‘~’运算符对应汇编not取反指令。

反汇编代码

        int  x = 2,y = 4,z = 6;

00EF4ED2  mov         dword ptr [x],2 

    int  x = 2,y = 4,z = 6;

00EF4ED9  mov         dword ptr [y],4 

00EF4EE0  mov         dword ptr [z],6 

    int num;

    printf("请输入一个整数:");

00EF4EE7  push        offset string "\xc7\xeb\xca\xe4\xc8\xeb\xd2\xbb\xb8\xf6\xd5\xfb\xca\xfd\xa3\xba" (0EF7B30h) 

00EF4EEC  call        _printf (0EF104Bh) 

00EF4EF1  add         esp,4 

    scanf_s("%d", &num);

00EF4EF4  lea         eax,[num] 

00EF4EF7  push        eax 

00EF4EF8  push        offset string "%d" (0EF7B48h) 

00EF4EFD  call        _scanf_s (0EF138Eh) 

00EF4F02  add         esp,8 

    if (y < num && z > num)

00EF4F05  mov         eax,dword ptr [y] 

00EF4F08  cmp         eax,dword ptr [num] 

00EF4F0B  jge         main+82h (0EF4F22h) 

00EF4F0D  mov         eax,dword ptr [z] 

00EF4F10  cmp         eax,dword ptr [num] 

00EF4F13  jle         main+82h (0EF4F22h) 

        printf("两个条件表达式同时为真时,逻辑与表达式为真!\n");

00EF4F15  push        offset string "\xc1\xbd\xb8\xf6\xcc\xf5\xbc\xfe\xb1\xed\xb4\xef\xca\xbd\xcd\xac\xca\xb1\xce\xaa\xd5\xe6\xca\xb1\xa3\xac\xc2\xdf\xbc\xad\xd3@"... (0EF7E40h) 

00EF4F1A  call        _printf (0EF104Bh) 

00EF4F1F  add         esp,4 

        if (x == num || y == num)

00EF4F22  mov         eax,dword ptr [x] 

00EF4F25  cmp         eax,dword ptr [num] 

00EF4F28  je          main+92h (0EF4F32h) 

00EF4F2A  mov         eax,dword ptr [y] 

00EF4F2D  cmp         eax,dword ptr [num] 

00EF4F30  jne         main+9Fh (0EF4F3Fh) 

        printf("其中任意一个表达式为真时,逻辑或表达式为真!\n");

00EF4F32  push        offset string "\xc6\xe4\xd6\xd0\xc8\xce\xd2\xe2\xd2\xbb\xb8\xf6\xb1\xed\xb4\xef\xca\xbd\xce\xaa\xd5\xe6\xca\xb1\xa3\xac\xc2\xdf\xbc\xad\xbb@"... (0EF85E8h) 

00EF4F37  call        _printf (0EF104Bh) 

00EF4F3C  add         esp,4 

        if (!num)

00EF4F3F  cmp         dword ptr [num],0 

        if (!num)

00EF4F43  jne         main+0B2h (0EF4F52h) 

        printf("num为零时,逻辑非表达式为真!\n");

00EF4F45  push        offset string "num\xce\xaa\xc1\xe3\xca\xb1\xa3\xac\xc2\xdf\xbc\xad\xb7\xc7\xb1\xed\xb4\xef\xca\xbd\xce\xaa\xd5\xe6\xa3\xa1\n" (0EF7BECh) 

00EF4F4A  call        _printf (0EF104Bh) 

00EF4F4F  add         esp,4 

   

        printf("num补码的值是%d\n", -num);//取num的补码

00EF4F52  mov         eax,dword ptr [num] 

00EF4F55  neg         eax 

00EF4F57  push        eax 

00EF4F58  push        offset string "num\xb2\xb9\xc2\xeb\xb5\xc4\xd6\xb5\xca\xc7%d\n" (0EF7FA4h) 

00EF4F5D  call        _printf (0EF104Bh) 

00EF4F62  add         esp,8 

        printf("num符号取反之后的值是%d\n", ~num);//num符号取反

00EF4F65  mov         eax,dword ptr [num] 

00EF4F68  not         eax 

00EF4F6A  push        eax 

00EF4F6B  push        offset string "num\xb7\xfb\xba\xc5\xc8\xa1\xb7\xb4\xd6\xae\xba\xf3\xb5\xc4\xd6\xb5\xca\xc7%d\n" (0EF7CF8h) 

00EF4F70  call        _printf (0EF104Bh) 

00EF4F75  add         esp,8 

    上述C语言的反汇编代码,我们可以清晰的看到,C语言中的条件表达式被翻译为CMP/JCC条件判断语句:

    if (y < num && z > num)

00EF4F05  mov         eax,dword ptr [y] 

00EF4F08  cmp         eax,dword ptr [num] 

00EF4F0B  jge         main+82h (0EF4F22h)  ;如果y>=num,则跳转到0EF4F22h地址处

00EF4F0D  mov         eax,dword ptr [z] 

00EF4F10  cmp         eax,dword ptr [num] 

00EF4F13  jle         main+82h (0EF4F22h)  ;如果z<=num,则跳转到0EF4F22h地址处

00EF4F1A  call        _printf (0EF104Bh)

    if (x == num || y == num)

00EF4F22  mov         eax,dword ptr [x]

 

结论

1.C语言中的条件表达式最终被翻译为汇编语言中的JCC条件判断语句。

2.C语言语句和高级汇编的决策伪指令非常相似。

3.如果把汇编语言中的寄存器改为编译器自动选取,CMP/JCC条件判断语句简化为条件表达式,汇编语言就变成了C语言。

本文摘自编程达人系列教材《汇编的角度——C语言》。资料下载:www.bcdaren.com

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

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

相关文章

SpringTask

SpringTask 介绍&#xff1a; Spring Task 是Spring框架提供的任务调度工具&#xff0c;可以按照约定的时间自动执行某个代码逻辑。Spring3.0以后自主开发的定时任务工具&#xff0c;可以看做是一个轻量级的Quartz框架。使用起来很简单&#xff0c;除spring相关的包外不需要额…

学习python第一天

1.输出 print("Hello, World!") 2.退出命令提升符 exit() 3.Python 缩进 实例 if 5 > 2:print("Five is greater than two!") 空格数取决于程序员&#xff0c;但至少需要一个。 您必须在同一代码块中使用相同数量的空格&#xff0c;否则 Python 会…

Fashion MNIST数据集介绍及基于Pytorch下载数据集

Fashion MNIST数据集介绍及基于Pytorch下载数据集 &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333;Fashion MNIST数据集简介&#x1f333;Fashion MNIST数据集的类别说明Fashion MNIST数据集图片示例 &#x1f333;基于PyTorch下载Fashion MN…

卸载Ubuntu双系统

卸载Ubuntu双系统 我们卸载Ubuntu双系统&#xff0c;可能出于以下原因&#xff1a; 1、Ubuntu系统内核损坏无法正常进入 2、Ubuntu系统分配空间不足&#xff0c;直接扩区较为复杂 3、以后不再使用Ubuntu&#xff0c;清理留出空间 123无论出于哪种原因&#xff0c;我们都是要…

Python调取Excel数据类似VLOOKUP

当需要通过某一信息&#xff0c;获取表格中其他信息时&#xff0c;比如想通过学号&#xff0c;直接拉取该学生的其他表格信息 可以通过如下代码&#xff1a; import xlrd #xlrd 常用的Excel读取库file "test.xls" #文件地址&#xff0c;注意xlrd可能无法…

【Android新版本兼容】onBackPressed()方法被弃用的解决方案

提示&#xff1a;此文章仅作为本人记录日常学习使用&#xff0c;若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、使用 AndroidX API 实现预测性返回手势1.1 添加依赖1.2 启用返回手势1.3 注册OnBackPressedCallback()方法来处理返回手势 一、使用 AndroidX API 实现预测…

Vue3_基础使用_2

这节主要介绍&#xff1a;标签和组件的ref属性&#xff0c;父子组件间的传递值&#xff0c;ts的接口定义&#xff0c;vue3的生命周期 1.标签的ref属性。 1.1ref属性就是给标签打标识用的&#xff0c;相当于html的id&#xff0c;但是在vue3中用id可能会乱&#xff0c;下面是ref…

分布式事务_学习笔记

分布式事务 0.学习目标 1.分布式事务问题 1.1.本地事务 本地事务&#xff0c;也就是传统的单机事务。在传统数据库事务中&#xff0c;必须要满足四个原则&#xff1a; 1.2.分布式事务 分布式事务&#xff0c;就是指不是在单个服务或单个数据库架构下&#xff0c;产生的事务…

杂题——试题 算法训练 区间最大和

分析&#xff1a; 如果使用两个for循环遍历所有情况&#xff0c;运行会超时解决运行超时的关键点在于&#xff1a;及时停止累加&#xff0c;丢弃当前的子序列 比如【1&#xff0c;-2&#xff0c;3&#xff0c;10】从第一个数字开始的子序列的和小于从第三个数字开始的子序列的和…

PSQL常用操作

目录 前言 准备工作 添加postgres用户 初始化数据库 启动服务 创建数据库 psql连接数据库 常规操作 数据库 schema相关 插件 其他 前言 老折腾&#xff0c;还是记录点啥吧...... 基于本地PG数据库(打包为绿色版本了)&#xff0c;实操记录&#xff0c;版本pgsql12…

关于华为应用市场上架,申请权限未告知目的被驳回问题的简单处理方式

关于华为应用市场上架过程中出现的【您的应用在运行时&#xff0c;未同步告知权限申请的使用目的&#xff0c;向用户索取&#xff08;存储、拍照&#xff09;等权限&#xff0c;不符合华为应用市场审核标准。】 使用方式&#xff1a; 1、引入 import permision from "/m…

【Jenkins】pipeline基本使用

目录 一、pipeline 二、创建pipeline项目 1、安装pipeline插件 2、创建pipeline项目 三、pipeline语法 1、pipeline组成 2、agent&#xff1a;指定流水线的执行位置&#xff0c;流水线中每个阶段都必须在某个地方执行 3、stage&#xff1a;阶段&#xff0c;代表流水线的…

编程实例分享,眼镜店电脑系统软件,配件验光管理顾客信息记录查询系统软件教程

编程实例分享&#xff0c;眼镜店电脑系统软件&#xff0c;配件验光管理顾客信息记录查询系统软件教程 一、前言 以下教程以 佳易王眼镜店顾客档案管理系统软件V16.0为例说明 如上图&#xff0c; 点击顾客档案&#xff0c;在这里可以对顾客档案信息记录保存查询&#xff0c;…

Linux(二)

远程登录 Xshell6 Xshell 是一个强大的安全终端模拟软件&#xff0c;它支持 SSH1, SSH2, 以及 Microsoft Windows 平台的 TELNET 协议&#xff1b; Xshell 可以在 Windows 界面下用来访问远端不同系统下的服务器&#xff0c;从而比较好的达到远程控制终端的目的&#xff1b; …

java hutool工具类实现将数据下载到excel

通过hutool工具类&#xff0c;对于excel的操作变得非常简单&#xff0c;上篇介绍的是excel的上传&#xff0c;对excel的操作&#xff0c;核心代码只有一行。本篇的excel的下载&#xff0c;核心数据也不超过两行&#xff0c;简洁方便&#xff0c;特别适合当下的低代码操作。 下载…

JAVA后端上传图片至企微临时素材

1.使用场景 在使用企业微信API接口中&#xff0c;往往开发者需要使用自定义的资源&#xff0c;比如发送本地图片消息&#xff0c;设置通讯录自定义头像等。 为了实现同一资源文件&#xff0c;一次上传可以多次使用&#xff0c;这里提供了素材管理接口&#xff1a;以media_id来…

【AI绘画UI+Windows部署】Fooocus:Controlnet原作者结合了sd的开源和Midjourney重新设计的UI

代码&#xff1a;https://github.com/lllyasviel/Fooocus windows一键启动包下载&#xff1a;https://github.com/lllyasviel/Fooocus/releases/download/release/Fooocus_win64_2-1-831.7z B站视频教程&#xff1a;AI绘画入门神器&#xff1a;Fooocus | 简化SD流程&#xff0c…

深度学习(12)--Mnist分类任务

一.Mnist分类任务流程详解 1.1.引入数据集 Mnist数据集是官方的数据集&#xff0c;比较特殊&#xff0c;可以直接通过%matplotlib inline自动下载&#xff0c;博主此处已经完成下载&#xff0c;从本地文件中引入数据集。 设置数据路径 from pathlib import Path# 设置数据路…

1E,Jarvis March

四个问题&#xff1a; 一&#xff0c;Jarvis March算法借鉴了什么算法&#xff1f; 二&#xff0c;如何确定初始点 三&#xff0c;如何获取凸包的边&#xff1f; 四&#xff0c;Jarvis March算法的好处在哪里&#xff1f; 首先看第一个问题&#xff0c; 一&#xff0c;Jarvis …

了解UDP发送过快导致的问题和对应解决方案

在当今这个以数据为核心的时代&#xff0c;企业对于数据传输的速度和稳定性有着日益增长的需求。UDP凭借其低延迟和高效率的特性&#xff0c;在实时通信和大规模数据传输领域扮演着关键角色。然而&#xff0c;UDP的无连接特性和缺乏可靠性也给数据传输带来了挑战&#xff0c;尤…