【C语言基础入门】2.C语言中四则运算、关系运算、逻辑运算与位运算_c语言四则运算-程序员宅基地

技术标签: # C语言学习之路  c语言  后端  开发语言  

文章目录

一、概述 

二、四则运算(+,-,*,/,%)

三、关系运算(<,>,<=,>=,==,!=)

四、逻辑运算与位运算 

五、深度剖析位运算


一、概述 

 C语言中支持下面4种类型的运算

运算类型 运算符
四则运算 +,-,*,/,%
关系运算 <,>,<=,>=,==,!=
逻辑运算 &&,||,!
位运算 &,|,^,>>,<<,~

二、四则运算(+,-,*,/,%)

  • 就是数学中的加,减,乘,除等运算
  • 遵循先乘除后加减的运算优先级
  • 可以使用括号改变运算顺序

 注意:

        C语言中的除法运算,其除数不能为0

         下面通过一段程序感受一下:

#include <stdio.h>

int main()
{
    int a = 5;
    int b = 2;
    double c = 3;

    c = a / b;

    printf("c = %f\n", c);

    c = a % b;

    printf("c = %f\n", c);

    return 0;
}

         下面为输出结果:

         通过上面的代码,可以得到一些小结论

  • 整型数的除法运算结果会舍弃小数部分
  • 取余(%)运算也是一种除法运算,结果为余数
  • 浮点数不能进行取余运算

三、关系运算(<,>,<=,>=,==,!=)

  •  比较两个值大小关系或相等关系的运算
  • 比较的结果为逻辑值 : 真(1),假(0)
  • 可以使用括号()改变关系运算的顺序

        如上面的图片所示,c 的值就为0 

        下面通过一段代码,感受一下:

#include <stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    int c = 3;

    c = a != b;

    printf("c = %d\n", c);

    c = a - b >= a + b;

    printf("c = %d\n", c);

    c = (a < b) + (c < b);

    printf("c = %d\n", c);

    return 0;
}

        下面为输出结果:

         小技巧:如果不同类型的运算同时出现在一个表达式中,那么尽量使用括号()指明运算顺序。

  •  运算优先级(优先级:四则运算 > 关系运算 > 赋值操作)
    • 四则运算
      • 正负号 > 乘除运算 > 加减运算
    • 关系运算
      • 大小比较运算 > 相等比较运算
    • 赋值操作

        下面看一段代码,深入感受一下运算优先级:

#include <stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    int c = 0;

    c = a != b + a * b;

    printf("c = %d\n", c);

    return 0;
}

         下面为输出结果,可以看出,c 的输出结果为1,为什么为1呢?这是由于乘法优先级大于加法优先级大于关系运算优先级,所以程序执行过程是这样,先计算 a * b,然后将 a * b 的结果 2 加上 b,得到4,最后再比较 a != 4,得到的结果当然为1啦,我们还可以通过反汇编来观察代码的执行过程。

c = a != b + a * b的汇编代码

          所以如果想得到a != b 再加上 a * b的结果,一定要记得加括号,如下:

#include <stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    int c = 0;

    c = (a != b) + (a * b);

    printf("c = %d\n", c);

    return 0;
}

         这样才能得到正确结果,如下所示:

小结:

  • 整型数除法有两种:取商(/),取余(%)
  • 浮点数除法与数学中除法运算相同,结果为浮点数
  • 不同运算的优先级不同,可使用括号改变运算优先级
  • 同一个表达式中应避免不同的运算类型(四则运算,关系运算)

四、逻辑运算与位运算 

  • 逻辑运算(&&,ll,!)
    • 逻辑运算的参与者为逻辑值(真或假)
    • 任何非零值在逻辑运算中都为
    • 任何零值在逻辑运算中都为

&&运算
左操作数 右操作数 结果
0 0 0
0 1 0
1 0 0
1 1 1
||运算
左操作数 右操作数 结果
0 0 0
0 1 1
1 0 1
1 1 1
  • 逻辑运算中的短路法则
    • 对于&&运算
      • 从左向右进行,如果有一个操作数为假,则整个表达式为假
      • 第一个为假的操作数之后的其它操作数不再计算
    • 对于||运算
      • 从左向右进行,如果有一个操作数为真,则整个表达式为真
      • 第一个为真的操作数之后的其它操作数不再计算
  • 取非运算(!)
    • 单目运算(只需要一个操作数),运算结果为逻辑值
      • 真值取非的结果为
      • 假值取非得结果为

         话不多说,上代码:

#include <stdio.h>

int main()
{
    int a = 1;
    int b = 2;
    int c = 0;

    c = a && b;

    printf("c = %d\n", c);

    c = !(a - b) || (c < b);

    printf("c = %d\n", c);

    c = 10000;
    c = !!c;

    printf("c = %d\n", c);

    return 0;
}

        下面为运行结果:

  •  位运算(&,|,~,^,<<,>>)
    • 直接对数据的二进制位进行操作
    • 位运算的基本单位是二进制位,所以也是一种0和1的操作
    • 可以使用括号()改变位运算的运算顺序
    • 位运算的操作数只能是整型数(浮点数不能直接进行位运算)
运算符 含义 示例 优先级
~ 按位求反 ~0101 -> 1010 1(高)
<< 左移:高位移出,低位补0 0011 << 1 -> 0110  2
>> 右移:低位移出,高位补符号位 0101 >> 2 -> 0001 2
& 按位与 0111 & 1100 -> 0100 3
^ 按位异或:相同为0,不同为1 0111 ^ 1100 -> 1011 4
| 按位或 0111 | 1100 -> 1111 5(低)

 注:

1.按位与和逻辑与的计算法相同:两者为1,结果为1,否则为0

2.按位或和逻辑或的计算法相同:两者为0,结果为0,否则为1

  • 位运算实例
    • 将整数5的第2个二进制位置1
    • 将整数7的第4个二进制位取反
    • 将整数2的最后两位取反
    • 将整数15右移2位,再将第2个二进制位置0
    • 设变量a的二进制数是10101101,若想通过运算a ^ b使得a的中间4位取反,其余位不变,则b的值是多少?

         代码如下:

#include <stdio.h>

int main()
{
    printf("c = %d\n", 5 | 2);
    printf("c = %d\n", 7 ^ 8);
    printf("c = %d\n", 2 ^ 3);
    printf("c = %d\n", (15 >> 2) & 13);
    printf("c = %d\n", 173 ^ 60);

    return 0;
}

        运行结果如下:

         这里需要特别注意:对某一位或者某几位取反可以用异或(^)运算,这在工程里常用!!!

  •  运算优先级(优先级从上到下为由高到低
    • 正负号>逻辑非>按位取反
    • 乘除>加减>按位左右移
    • 大小比较运算>相等比较运算
    • 按位与>按位异或>按位或
    • 逻辑与>逻辑或
    • 赋值操作
  •  小结
    • 逻辑运算中有特殊的短路法则,结果确定后不再向下计算
    • C语言中的真值对应非零值,假值对应零值
    • 位运算直接对数据的二进制位进行操作
    • 位运算的操作数只能是整型数(浮点数不能直接进行位运算)

五、深度剖析位运算

  •  不同类型的本质在于:
    • 占用的内存大小不同,如:short占用2字节,int占用4字节
    • 表示具体数据的方式不同
      • 正整数用原码表示,负整数用补码表示
      • 整数型和浮点型的二进制表示不同
  • 位运算时需要明确的知道的事
    • 操作数的类型(占用的内存大小)
    • 操作数是正数还是负数(符号位,数据表示)
    • 不同类型的操作数先自动对齐再进行位运算(补符号位)

         如下面的一段代码:

short a = 1;
int b = 4;
int c = a | b;
printf("c = %d\n",c);

        b为int类型,占4个字节,a为short类型,占2个字节。所以a要先要补符号位,由于a是正数,所以补0,这样就可以进行位运算了,得出c的结果为5。 

        下面来看一段代码:

#include <stdio.h>

int main()
{
    short a = 1;
    short b = 2;
    int c = a - b;

    c = c >> 4;

    printf("c = %d\n", c);

    c = c * -1 * 16 >> 4;

    printf("c = %d\n", c);

    printf("c = %d\n", 16 << 2);

    return 0;
}

         下面为输出结果:

  •  小结论
    • 正数符号位为0,右移运算时,高位补0,低位移除
    • 负数符号位为1,右移运算时,高位补1,低位移除
    • 左移运算时,最高位移除,低位补0
    • 最高位的具体位置,由数据类型决定
  • 类型补充小知识
    •  char 字符型,一个字节的整型,范围[-128,127]
    • 字符数据(单引号括起来的字符)的本质是整型数
    • char类型的变量可以打印为整数或者字符

        再看一段代码:

#include <stdio.h>

int main()
{
    char c = 'A';
    short a = c;
    int b = c;

    printf("c = %c\n", c);
    printf("c = %d\n", c);
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    c = 0x40;

    printf("c = %x\n", c);
    printf("c = %d\n", c);

    c = c << 1;

    printf("c = %d\n", c);

    c = c << 1;

    printf("c = %d\n", c);

    return 0;
}

        下面为输出结果:

         需要注意的是,因为c为char类型,所以64左移1位后,用二进制表示为1000 0000,最高位的1表示符号位,所以就是-128。

  • 小结 
    • 不同类型的本质区别是:占用内存不同数据表示不同
    • 右移运算时,高位补符号位,低位移除
    • char是只占用一个字节的整型,可表示英文字符
    • 数据符号位的具体位置由数据类型决定
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43129713/article/details/121035094

智能推荐

apksigner完成apk的签名_apksigner 签名-程序员宅基地

文章浏览阅读2.3k次。有时候用第三方加固平台加固以后会让我们重新签名。还有就是上应用市场的时候,如果以前该应用已经在市场上上传过了,由于后面业务原因换了开发者账号再去上传就会提示我们去认领一个没有签名的包(unsign.apk),然后去签名上传进行MD5签名验证,如下图看到上面的提示不要慌,不就是加个签名么,apksigner就是SDK自带的签名工具,处于F:\android-sdk\build-tools\xxx目录下将上面的路径配置到系统环境变量path中,打开cmd,切换到unsign.apk目录下,建议.._apksigner 签名

java内省机制及PropertyUtils使用方法_propertyutils.snaketoline(field.getname());-程序员宅基地

文章浏览阅读1.3k次。背景 一般情况下,在Java中你可以通过get方法轻松获取beans中的属性值。但是,当你事先不知道beans的类型或者将要访问或修改的属性名时,该怎么办?Java语言中提供了一些像java.beans.Introspector这样类,实现了在运行时检测Java类并确定属性get和set方法的名称,结合Java中的反射机制就可以调用这些方法了。然而,这些APIs使用起来比较_propertyutils.snaketoline(field.getname());

LeetCode 516. Longest Palindromic Subsequence--最长回文子序列长度_leetcode longestpalindromesubseq连续字符不想等,长度为偶的回文子序列-程序员宅基地

文章浏览阅读536次。Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.Example 1:Input:"bbbab"Output:4One possible longest palind_leetcode longestpalindromesubseq连续字符不想等,长度为偶的回文子序列长度

Android自定义View之自定义加载进度条(二)-程序员宅基地

文章浏览阅读189次。本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点自定义加载进度条Android自定义View之手把手带你自定义一个进度条上次我们已经把实线和虚线都绘制好了,这次我们就主要来解决更新的问题:怎么随着时间的推移逐渐地绘制进度条怎么在绘制的过程中加速进度条的绘制首先我们来解决第一个问题,也就是随着时间更新我们的..._setvalueinterpolator

c#判断字符串是否json-程序员宅基地

文章浏览阅读5.7k次。来源:https://www.cnblogs.com/cyq1162/p/3841766.html下载地址:  https://github.com/cyq1162/cyqdata/blob/master/Tool/JsonSplit.cs  https://github.com/cyq1162/cyqdata  using System;using System.C..._c#判断是json还是xml

python读取eml文件并用正则匹配邮箱_python 如何查看eml文件-程序员宅基地

文章浏览阅读992次。python读取eml文件并用正则匹配邮箱_python 如何查看eml文件

随便推点

Jquery插件之DataTables初探_jquery datatables 英文-程序员宅基地

文章浏览阅读2.5k次。今天闲来无事,就研究了一下Jquery的DataTables插件。感觉效果不错,支持排序和内容过滤(查询),在这里向大家推荐一下^_^不得不说之前犯了一个错误,这个插件应该叫做DataTable,而我把它当成了tablesort,实在不好意思。。。。。可以直接到官网上去下载下来,单击http://www.datatables.net/到官网上看看,什么API、demo之类的_jquery datatables 英文

算法:逆序对-程序员宅基地

文章浏览阅读8.5k次,点赞8次,收藏11次。逆序对什么是逆序对呢?百度百科这样解释:设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。定义:对于一个包含N个非负整数的数组A[1…n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。例如,数组(3_逆序对

SLAM导航机器人零基础实战系列:(四)差分底盘设计——3.底盘通信协议_slam 实战-程序员宅基地

文章浏览阅读1.2k次。SLAM+语音机器人DIY系列:(四)差分底盘设计——3.底盘通信协议摘要 运动底盘是移动机器人的重要组成部分,不像激光雷达、IMU、麦克风、音响、摄像头这些通用部件可以直接买到,很难买到通用的底盘。一方面是因为底盘的尺寸结构和参数是要与具体机器人匹配的;另一方面是因为底盘包含软硬件整套解决方案,是很多机..._slam 实战

LOJ #6010. 「网络流 24 题」数字梯形-程序员宅基地

文章浏览阅读89次。#6010. 「网络流 24 题」数字梯形题目描述给定一个由n nn行数字组成的数字梯形如下图所示。梯形的第一行有m mm个数字。从梯形的顶部的m mm个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。分别遵守以下规则:从梯形的顶至底的m mm条路径互不相交;从梯形的顶至底的m mm..._7-60 数字梯形 (110 分) 给定一个由n行数字组成的数字梯形如下图所示。梯形的第一

Ubuntu20.04 + RTX 3090(兼容RTX 2080 Ti) + Pytorch1.7配置方法_2080ti ubuntr20.04-程序员宅基地

文章浏览阅读2.2k次。背景介绍:由于在Ubuntu16.04系统上安装RTX 3090显卡驱动有点吃力(各种Error和不兼容),使用最新Ubuntu20.04系统搭配最新的RTX 3090显卡配置最新的Pytorch【(*^▽^*)】前期准备: 1、Ubuntu20.04下载:Ubuntu20.4_amd64_desktop.iso 2、UNtebootin光盘刻录软件下载:unetbootin,选择Windows下载 3、NVID..._2080ti ubuntr20.04

Struts + Spring +ibatis 整合开发步骤_struts+spring+ibatis-程序员宅基地

文章浏览阅读329次。一.添加Spring 、Struts框架对web.xml文件的修改1. 添加Spring框架2. 在web.xml中引入Spring配置文件(注意:applicationContext.xml文件的路径)context-param> param-name>contextConfigLocationparam-name> param-v_struts+spring+ibatis