当前位置: 首页 > news >正文

爱上C语言:操作符详解(下)

🚀 作者:阿辉不一般
🚀 你说呢:生活本来沉闷,但跑起来就有风
🚀 专栏:爱上C语言
🚀作图工具:draw.io(免费开源的作图网站)
请添加图片描述

如果觉得文章对你有帮助的话,还请点赞,关注,收藏支持博主,如有不足还请指点,博主及时改正,感谢大家支持!!!

文章目录

  • 🚀前言
  • 🚀整型的存储以及原、反、补码
  • 🚀移位操作符
    • ✈️左移操作符(<<)
    • ✈️右移操作符(>>)
  • 🚀位操作符
    • ✈️一道变态面试题
  • 🚀单目操作符
    • ✈️ 逻辑反操作(!)
    • ✈️sizeof
  • 🚀剩下的操作符
  • 🚀复杂的表达式如何计算
    • ✈️优先级
    • ✈️结合性

🚀前言

大家好啊😉!承接之前的操作符上篇,今天阿辉将介绍剩下的操作符,包括移位操作符,位操作符以及单目操作符,持续输出干货中,关注阿辉不迷路哦 😘 ,内容干货满满😋,接下来就跟着阿辉一起学习吧👊

🚀整型的存储以及原、反、补码

介绍移位操作符和位操作符前得先了解整型在内存中的存储以及原反补码,阿辉上篇文章上篇文章整型的存储里面有详细的讲解(点击直接跳转哦 😘)

🚀移位操作符

移位操作符有何作用?
移位操作符移动的是数据在内存中存储的补码的二进制位,其中移位操作符的“位”字就是指二进制位

移位操作符有左移操作符右移操作符两种

✈️左移操作符(<<)

左移操作符怎么使用呢?

左操作数 << 右操作数
左操作数是要被左移位的数
右操作数是要左移移动的位数

左移操作符的规则就是左边丢弃,右边补0
我们来看一个🌰栗子

int main()
{int a = 10;0000 0000 0000 0000 0000 0000 0000 1010 ->a原码0000 0000 0000 0000 0000 0000 0000 1010 ->a反码 0000 0000 0000 0000 0000 0000 0000 1010 ->a补码 int b = a << 2;0000 0000 0000 0000 0000 0000 0010 1000 ->b补码 b也就是40return 0;
}

在这里插入图片描述
是不是有点懵😏,别急阿辉用图演示👇
请添加图片描述
现在是不是对左移操作符用法清晰多了😁 ,上述演示仅仅使用了正数,不过负数同样可以,负数仅仅是多了原反补码之间的转换

✈️右移操作符(>>)

右移操作符的使用

左操作数 >> 右操作数
左操作数是要被右移位的数
右操作数是要右移移动的位数

右移操作符的规则

  • 算术右移:左边补符号位,右边丢弃
  • 逻辑右移:左边补0,右边丢弃

对于使用逻辑右移还是算术右移从语言并未明确规定,但大部分编译器都使用算术右移,对于无符号数使用逻辑右移

算术右移:左移用正数,咱们这次用负数演示👊

int main()
{int a = -10;1000 0000 0000 0000 0000 0000 0000 1010->a原码1111 1111 1111 1111 1111 1111 1111 0101->a反码1111 1111 1111 1111 1111 1111 1111 0110->a补码int b = a >> 2;1111 1111 1111 1111 1111 1111 1111 1101->b补码1000 0000 0000 0000 0000 0000 0000 00101000 0000 0000 0000 0000 0000 0000 0011->b原码 也就是-3return 0;
}

请添加图片描述

逻辑右移:逻辑右移也与上述算数右移的运算是类似的,不过逻辑右移不管你是正数还是负数,左边通通补0

注意

  • 移位操作符的操作数只能为整型
  • 对于移位运算符,不要移动负数位,这个是标准未定义的
  • a>>1a<<1这两个都不会改变a的值,就像a+1这样并不会改变a的值

🚀位操作符

位操作符分类

& 按位与
| 按位或
^ 按位异或
~ 按位取反
& | ^ 这三个有两个操作数
~ 只有一个操作数

这里的位同样指的是二进制位,它们操作的依然是内存中的补码
&按位与: 两操作数内存中的补码两相同二进制位均为1就为1,其中一个0就为0
🌰栗子

int main()
{int a = 3;0000 0000 0000 0000 0000 0000 0000 0011 -> 3的原反补码int b = -5;1000 0000 0000 0000 0000 0000 0000 0101 -> -5的原码1111 1111 1111 1111 1111 1111 1111 1010 -> -5的反码1111 1111 1111 1111 1111 1111 1111 1011 -> -5的补码int c = a & b;1111 1111 1111 1111 1111 1111 1111 1011 -> -5的补码0000 0000 0000 0000 0000 0000 0000 0011 -> 3的补码0000 0000 0000 0000 0000 0000 0000 0011 -> 按位与结果符号位为0,原反补码相同,值为3return 0;
}

在这里插入图片描述
| 按位或: 两操作数内存中的补码两相同二进制位均为0就为0,其中一个1就为1

|&的用法类似这里就不举例子了

^按位异或: 两操作数内存中的补码两相同二进制位相同为0,相异为1
🌰栗子

int main()
{int a = 3;0000 0000 0000 0000 0000 0000 0000 0011 ->3原反补码int b = 3;int c = a ^ b;0000 0000 0000 0000 0000 0000 0000 0011 ->3原反补码0000 0000 0000 0000 0000 0000 0000 0011 ->3原反补码0000 0000 0000 0000 0000 0000 0000 0000 异或结果int d = c ^ a;0000 0000 0000 0000 0000 0000 0000 0000 ->c0000 0000 0000 0000 0000 0000 0000 0011 ->a0000 0000 0000 0000 0000 0000 0000 0011 异或结果int e = a ^ a ^ b;int f = a ^ b ^ a;return 0;
}

在这里插入图片描述
由上面的例子,我们可以得到以下结论👇

相同数字异或结果为0即a ^ a = 0,0与任何数字异或仍为该数字即0 ^ a = a
并且^支持交换律与结合律即a ^ b ^ c = a ^ c ^ b

~按位取反: 操作数在内存中的补码按二进制位0改为11改为0
🌰栗子

int main()
{int a = 0;0000 0000 0000 0000 0000 0000 0000 0000 ->0的原反补码1111 1111 1111 1111 1111 1111 1111 1111 ->按位取反结果1000 0000 0000 0000 0000 0000 0000 0001 ->原码值为-1int c = ~a;return 0;
}

在这里插入图片描述
注意:他们的操作数必须为整数

✈️一道变态面试题

不创建新变量交换两个整数

int main()
{int a = 10;int b = 12;a = a ^ b;b = a ^ b;a = b ^ a;return 0;
}

上面代码是不是很懵 😆,第一次我也很懵逼,我们接着看👇

a = a ^ b这时a的值不在是10而是10 ^ 12,然后b = a ^ b实际上是b = 10 ^ 12 ^12,由上面我们知道的^的特点可知10 ^ 12 ^ 12 = 10,这时b = 10,在看这句a = a ^ b实际上是a = 10 ^ 12 ^ 10,而10 ^ 12 ^ 10 = 12这时a = 12所以ab的值完成了交换

🚀单目操作符

单目操作符的分类:

!           逻辑反操作
-           负值
+           正值
&           取地址
sizeof      操作数的类型长度(以字节为单位)
~           对一个数的二进制按位取反
--          前置、后置--
++          前置、后置++
*           间接访问操作符(解引用操作符)
(类型)       强制类型转换

✈️ 逻辑反操作(!)

🌰栗子

int main()
{int a = 0;int b = 4;if (!(b == 4))printf("真");printf("%d ", !a);printf("%d\n", !b);return 0;
}

在这里插入图片描述
逻辑反操作即把0 (假) 改为1 (真) ,非0 (真) 改为0 (假)

✈️sizeof

sizeof这个操作符,sizeof是由来计算变量(类型)所占空间的大小,不关注存储的内容,单位是字节

int main()
{int a = 2;int b[4] = { 0 };char c = '1';printf("%u\n", sizeof(b));printf("%u\n", sizeof(b[0]));printf("%u\n", sizeof(a));printf("%u\n", sizeof(c));printf("%u\n", sizeof(int));return 0;
}

在这里插入图片描述
sizeof的操作数为数组名时计算的整个数组的大小

🚀剩下的操作符

其中有一些过于简单相信大家都掌握了,至于**结构体成员访问操作符(.)和(->)**会在后续结构体章节详细讲到, **解引用操作符(*)和取地址操作符(&)**会在后续数组篇中讲解

🚀复杂的表达式如何计算

C语言的操作符有2个重要的属性:优先级、结合性,这两个属性决定了表达式求值的计算顺序

✈️优先级

相邻操作符的优先级高的先算

int main()
{int a = 3;int b = 4;a - b * a;
}

上述代码*乘的优先级更高先算b * a而不是先算a - b

✈️结合性

当相邻两操作符优先级相同就要看结合性了,左结合从左向右计算,右结合从右向左计算

int main()
{int a = 3;int b = 4;a / b * a;
}

上述代码中/*的优先级相同都是左结合,因此先算a / b
下面是一张操作符优先级与结核性的表
在这里插入图片描述
虽然我们知道了操作符的结合性与优先级,但这并不能保证表达式具有唯一计算路径,因此尽量不要写过于复杂的表达式很容易出bug


到这里,阿辉今天对于C语言中操作符的分享就结束了,希望这篇博客能让大家有所收获, 如果觉得阿辉写得不错的话,记得给个赞呗,你们的支持是我创作的最大动力🌹
请添加图片描述

相关文章:

  • 软路由R4S+iStoreOS实现公网远程桌面局域网内电脑
  • Python中神奇的「type」,即可查看类型,又可以创建对象
  • Postman:API测试之Postman使用完全指南
  • [Python学习笔记]Requests性能优化之Session
  • spark性能调优 | 内存优化
  • 科学上网导致Adobe软件运行弹出This non-genuine Adobe app will be disabled soon,尝试解决办法
  • bug:Junit5报错,@SpringBootTest没有运行
  • C#语言的由来与发展历程
  • uart控制led与beep
  • QT绘图设备
  • 大数据-之LibrA数据库系统告警处理(ALM-12051 磁盘Inode使用率超过阈值)
  • torch - 张量Tensor常见的形式
  • Docker Golang 开发环境搭建指南
  • 【MATLAB源码-第77期】基于matlab的OCDM系统在AWGN信道下理论误码率和实际误码率对比仿真。
  • IP池大小重要吗?
  • 网络传输文件的问题
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 【知识碎片】第三方登录弹窗效果
  • create-react-app项目添加less配置
  • ES6核心特性
  • FineReport中如何实现自动滚屏效果
  • If…else
  • Java Agent 学习笔记
  • java多线程
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 目录与文件属性:编写ls
  • 网络应用优化——时延与带宽
  • 在Docker Swarm上部署Apache Storm:第1部分
  • Linux权限管理(week1_day5)--技术流ken
  • Spring Batch JSON 支持
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​ubuntu下安装kvm虚拟机
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #在 README.md 中生成项目目录结构
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (2)Java 简介
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (C语言)二分查找 超详细
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (译) 函数式 JS #1:简介
  • (转)我也是一只IT小小鸟
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .Net 8.0 新的变化
  • .net core 实现redis分片_基于 Redis 的分布式任务调度框架 earth-frost
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET Remoting学习笔记(三)信道
  • .NET 表达式计算:Expression Evaluator
  • .net 提取注释生成API文档 帮助文档
  • .net流程开发平台的一些难点(1)