前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C语言】操作符还能这样?

【C语言】操作符还能这样?

作者头像
平凡的人1
发布2022-11-15 14:38:20
7880
发布2022-11-15 14:38:20
举报
文章被收录于专栏:从小白开始修炼

✨作者:@平凡的人1 ✨专栏:《C语言从0到1》 ✨一句话:凡是过往,皆为序章 ✨说明: 过去无可挽回, 未来可以改变


文章目录

🎬前言

大家好,今天给大家带来的是操作符的内容,操作符可能有的人看来是比较简单的,并没有什么重要的内容,很简单,不就是加减乘除嘛,但是实际上呢,背后却有着许多值得我们去学习、去推敲的地方,通过操作符,我们能够学到很多的知识,对于C语言的学习具有很大的意义,希望通过这篇博客,你能够有所收获,能够得到进一步的提升,这才是最主要的!下面让我们来一起看一看把。💖

image-20220511085230891
image-20220511085230891

说到操作符,开始之前,我们先来简单梳理一下内容架构,先了解操作符的类型有哪一些:👇

🚀操作符的分类

💫算术操作符 💫移位操作符 💫位操作符 💫赋值操作符 💫单目操作符 💫关系操作符 💫逻辑操作符 💫条件操作符 💫逗号表达式 💫下标引用、函数调用和结构成员


📘下面,我们从上往下开始介绍起。

🚀算术操作符

/ * + - %

  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
  2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
  3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数

情况1和情况3:浮点数不能用%

image-20220511104500584
image-20220511104500584

情况2:有浮点数就执行浮点数除法

image-20220511105134528
image-20220511105134528

🚀移位操作符

移位操作符分为【左移操作符】、【右移操作符】

左移操作符:<< 右移操作符 :>> 与此同时,我们还要注意: 移位操作符的操作数只能是整数

🚩左移操作符

左移操作符比较简单,根据原码反码补码的移位规则:

左边抛弃、右边补0

怎么理解?来,看一小段代码:

image-20220511110515482
image-20220511110515482

a<<1:

image-20220511111114402
image-20220511111114402

🚩右移操作符

右移操作符相对来说比较难,分为两种移位:

  1. 逻辑移位左边用0填充,右边丢弃
  2. 算术移位左边用原该值的符号位填充,右边丢弃
image-20220511114232507
image-20220511114232507

我们基于上面代码来看看右移操作符在编译器中是逻辑位移还是算术位移,先来分析一波:

image-20220511121017131
image-20220511121017131

此时,我们已经知道的补码,如果编译器是算术移位的话,将会打印出-1如果是逻辑移位的话,将会打印出1,结果会是什么呢?让我们来看看:

image-20220511121214967
image-20220511121214967

结果是-1.其实很显然,这才符合实际,说明编译器是算术移位计算的。

这时候,可能有人会问了,那移动负数位呢?

❌可以明确的告诉你:对于移位运算符,不要移动负数位,这个是标准未定义的

如:int a = 5;

​ a>>-1;//这是错误的

编译都过不了

🚀位操作符

我们先来看看位操作有哪些:

& 按位与 ——同1才为1,其他为0 | 按位或——有1就是1 ^ 按位异或 ——相同为0,不同为1 注:操作数必须是整数。

这里的位:指的是二进制位,根据原、反、补码进行运算。

这些操作符有什么用呢?我们来应用一下^按位异或:我们通过一个例子来说明⏩

让我们来看一道题目:

🚩不创建临时变量交换两个整数

第一种方法:两数进行相加减,但是可能会出现溢出问题,故此方法在这里不做展示。

第二种方法:这时候位操作符就派上用场了,来看看💨

image-20220511122501236
image-20220511122501236

懵了?别急,先来捋一捋:

我们知道: 0按位异或任何数都是任何数,即0^a = a;为什么?按位异或:相同为0,相异为1 任何数按位异或本身就是0,即a^a = 0; 满足分配律! 解释见下:

举个例子,0^1 = 1

image-20220511123433226
image-20220511123433226

1^1也是同理。

如何理解分配律呢?测试一下就行了:

image-20220511123634264
image-20220511123634264

结果是一样的,与顺序无关。

好了,到了这里,我们在重新看一看刚开始的题目:交换两个数,这时候是不是就更加理解了!

我们在来看另一个题目:

🚩求一个整数存储在内存中的二进制中1的个数

image-20220511133700161
image-20220511133700161

🚀赋值操作符

比较简单,简单来说,就是可以对变量进行赋值

除此之外,赋值操作符可以连续使用,比如:

image-20220511134309007
image-20220511134309007

不过,可不能这样子赋值,避免出错:

image-20220511134653166
image-20220511134653166

🚀复合赋值符

将运算符写成复合的效果

+= -= *= /= %= >>= <<= &= |= ^=

比如:

image-20220511135017887
image-20220511135017887

上面两个式子是等价的,其他运算符一样的道理。这样写更加简洁。

🚀单目操作符

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

下面,直接进入代码进行练习:

image-20220511140735520
image-20220511140735520

关于sizeof我前面的博客就已经有写过了,可以求变量(类型)所占空间的大小

再来练习一道题:

image-20220511141117892
image-20220511141117892

前置++和前置–

image-20220511141421884
image-20220511141421884

后置++和后置–

image-20220511141603607
image-20220511141603607

🚀关系操作符

> >= < <= != 用于测试“不相等” == 用于测试“相等

上面几个操作符较为简单,唯一比较容易犯错的地方在于**== 和 =**不小心写错

🚀逻辑操作符

&& 逻辑与 || 逻辑或

我们要区分逻辑与和按位与 区分逻辑或和按位或

代码语言:javascript
复制
1&2----->0//进行二进制位运算
1&&2---->1//并且,0为假,非0为真
1|2----->3//进行二进制位运算
1||2---->1//获知,0为假,非0为真

下面,通过一道题目来认识:

image-20220511142524129
image-20220511142524129

分析:

image-20220511142758795
image-20220511142758795

🚀条件操作符

代码语言:javascript
复制
a>b?a(如果a>b结果为a):b(否则为b);

简单来说,条件操作和和ifelse语句一定程度上是可以相互转换的。我们来看个例子

image-20220511143851316
image-20220511143851316

下面转换成条件操作符方式:

image-20220511143927074
image-20220511143927074

🚀逗号表达式

什么是逗号表达式❓

逗号表达式,就是用逗号隔开的多个表达式。 逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

直接来看代码:

image-20220511144441810
image-20220511144441810

从左到右依次计算,最有一个式子为结果。

好了,基于上面这个例子简单说明了什么是逗号表达式,下面,我们来一起看看下标引用、函数调用和结构成员

🚀下标引用、函数调用和结构成员

[ ] 下标引用操作符

其实在数组的时候我们早就遇到过了。这不过这里单独拿了出来:

代码语言:javascript
复制
int arr[10];//创建数组
 arr[9] = 10;//实用下标引用操作符。
 [ ]的两个操作数是arr和9。

( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。在学习函数相关知识就已经常用了,下面来举个例子:

image-20220511145905599
image-20220511145905599

访问一个结构的成员

两种方式访问:

结构体.成员名 结构体指针->成员名

下面来给大家演示一下这两种方式的使用及其区别:

image-20220511150858828
image-20220511150858828

输出结果是什么?一个是传值调用,另一个是传址调用。

image-20220511151007564
image-20220511151007564

一个没改变,另一个有改变。这是因为第一个形参是实参的临时拷贝,形参的改变影响不了实参。这是反复强调的问题了

🚀拓展:表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。 同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

🚩隐式类型转换

C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

那整型提升究竟有什么意义呢❓

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度 一般就是int的字节长度,同时也是CPU的通用寄存器的长度。 因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长 度。 通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令 中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转 换为int或unsigned int,然后才能送入CPU去执行运算。

那如何进行整型提升呢?

整型提升是按照变量的数据类型的符号位来提升的

我们来看个例子:

image-20220511151801348
image-20220511151801348
image-20220511151817582
image-20220511151817582

为什么输出结果是c呢❓

答:a,b要进行整形提升,但是c不需要整形提升 a,b整形提升之后,变成了负数,所以表达式 a= , b 的结果是假,但是c不发生整形提升,则表达式 c0xb6000000 的结果是真==

在来看一个例子:

image-20220511152416583
image-20220511152416583

c只要参与表达式运算,就会发生整形提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字 节. 表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof© ,就是1个字节

🚩 算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。

long double double float unsigned long int long int unsigned int int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。

🚩操作符的属性

复杂表达式的求值有三个影响的因素。

  1. 操作符的优先级 2. 操作符的结合性 3. 是否控制求值顺序。

两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

✍结语

通过上面的介绍,相信你对操作符又有了不一样的理解。同时,本次博客也到了尾声,如果觉得不错的话,记得支持一下!🌹

微信图片_20220428130649
微信图片_20220428130649
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 🎬前言
  • 🚀操作符的分类
  • 🚀算术操作符
  • 🚀移位操作符
    • 🚩左移操作符
      • 🚩右移操作符
      • 🚀位操作符
        • 🚩不创建临时变量交换两个整数
          • 🚩求一个整数存储在内存中的二进制中1的个数
          • 🚀赋值操作符
          • 🚀复合赋值符
          • 🚀单目操作符
          • 🚀关系操作符
          • 🚀逻辑操作符
          • 🚀条件操作符
          • 🚀逗号表达式
          • 🚀下标引用、函数调用和结构成员
          • 🚀拓展:表达式求值
            • 🚩隐式类型转换
              • 🚩 算术转换
                • 🚩操作符的属性
                • ✍结语
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档