赞
踩
hello呀!小伙伴们!!!
大家在写代码的时候避免不了会用到各种各样的操作符,那么,你真的了解操作符嘛?
下面就跟着小刘同学来学习一下关于C语言操作符的一二事吧~当然,如果大家觉得小刘同学的讲解不错的话,可以点一波关注哦~
+ - * / %
关于以上的几个算术操作符,我们在平时的代码练习中是经常使用的,对于它们,小刘在这里不做过多的介绍,但是我们在使用时要注意以下的几点:
1.除了“%”操作符以外,其他的几个操作符可以作用于整数和浮点数
2.对于“/”操作符:如果两个操作数都是整数,执行整数除法。当两个操作符中有一个或者两个都是浮点数时,执行的是小数除法。
例如:整型的除法:1/2——>0
浮点型的除法:1.0/2——>0.5
3.“%”操作符(取模操作符)的两个操作数必须为整数。返回的是整除后的余数。
例如:3%2——>1
<< 左移操作符>> 右移操作符移位操作符的操作数只能是整数
一个数值可以用2进制,10进制或者8进制表示。这些进制仅仅只是数值的一些表示形式而已。
例如:
10进制中的每一位都是由0~9组成的
8进制中的每一位都是有0~7组成的
2进制中的每一位都是由0~1组成的
整数的二进制表示有三种:
原码
反码
补码
正整数的原码,反码,补码相同
负整数的反码是:原码的符号位不变,其他位按位取反。补码:反码加一。
例如:
7
原码:0000 0000 0000 0000 0000 0000 0000 0111
|
最高位是符号位:如果是0则表示是正数,如果是1则表示是负数。
7为正数,所以,它的原反补是相同的。
-5
原码:1000 0000 0000 0000 0000 0000 0000 0101
反码:1111 1111 1111 1111 1111 1111 1111 1010
补码:1111 1111 1111 1111 1111 1111 1111 1011
-5为负数,所以它的原反补是要自己计算的。
我们的整数在内存中存储的是补码。
而移位操作符移动的是我们在内存中存储的补码的二进制位
左移操作符
移位规则:左边抛弃,右边补0
左移存在*2的效果。
而左移操作符到底是怎么回事呐?下面,小刘同学就带着大家揭晓这个答案:
首先,我们先在内存中为a=7开辟一块空间:
接着,根据:b=a<<1;移动过后会出现下图所示的样子:左边丢失一位,右边缺少一位。根据左移操作符的运算规则:左边丢弃,右边补0。我们得到,b的二进制序列为:0000 0000 0000 0000 0000 0000 0000 1110——>转化为十进制为14。
多次试验后,推出:左移操作符存在*2的结果。对于负数来说过程也是一样的。并且在这个过程中,a的值不存在变化。
右移操作符
移位规则:1.逻辑移位左边用0填充,右边丢弃2.算术移位——>vs一般为算术移位左边用原该值的符号位填充,右边丢弃
以上两个代码对比可得,右移不存在一个固定的效果。
我们再来分析一下右移操作符的操作过程:
首先,如同我们在分析左移操作符时相同,我们先在内存中给 int a=7;开辟一块内存空间:
根据int b=a>>1;存在下图:右移操作符遵循哪个移动规则是根据编译器来决定的。而vs编译器一般都为算术移位:故存在:向左边补原本的值:0,右边舍弃。所以,我们的b=0000 0000 0000 0000 0000 0000 0000 0011——>转化为十进制数为3。与我们的代码实际结果相同,所以我们可以确定目前小刘同学所使用的编译器vs2022属于算术移位。
而,我们该如何验证自己的编译器到底是遵循算术移位还是逻辑移位呢?这个时候我们的负数就要派上用场了。这个时候,我们将上述代码的a=7改写为a=-7。
此时,-7的原码为:1000 0000 0000 0000 0000 0000 0000 0111.
反码为:1111 1111 1111 1111 1111 1111 1111 1000
补码为:1111 1111 1111 1111 1111 1111 1111 1001
此时,如果编译器是逻辑移位,我们得到的结果为:-6。
要注意,编译器在输出时输出的是数值的二进制原码。
注意:对于移位运算符,不要移动负数位,这个是标准未定义的。
& 按(二进制)位与
| 按(二进制)位或
^ 按(二进制)位异或 ——>如果是两个相同的数字异或,结果为0
——>0^A的结果是A
——>异或操作符支持交换律
注意:它们的操作符必须是整数
在进行运算时,参与计算的是整数的补码,而不是它的原码
关于按位与操作符,根据名字我们就可以得知,这个操作符的作用是将二进制代码按位与
那么,具体该如何使用呐?下面就跟着小刘同学来看一看吧!
以上代码是如何得出这个结果的呐?
而,c的符号位为0,即c是整数,所以,c的原反补是相同的。
由此,我们可得:按位与——>相对应的二进制码,存在0就是0,两个全为1才是1.
关于按位与操作符,我们也可以通过这样子的方法来得知,按位与的功能:
对上述代码进行分析:
所以,我们可以得知,按位或操作符——>有1为1,全0为0.
对于按位异或操作符,我们亦可以采用同样的方法来理解:
以上代码的分析见下图:
由上图的分析结果,我们可以总结异或的规律为:相同为0,相异为1
讲到这里,大家对位操作符的理解是不是又加深了一步呐?
那么,下面我们就来做一道题吧:
题目要求:不能创建临时变量(第三个变量),实现两个数的交换。
这道题我们该如何分析呐?
首先,我们可以使用加减法来进行计算。具体代码如图:
虽然,目前以上代码没有出现问题。但是,此时,a和b都是整型,它们有自己的上限。假设这个时候,a和b的值都非常的大,但是并没有超出它们的上限。此时,a+b的值一定也非常大,甚至会超出整型类型的上限。这个时候,我们就不能够继续使用上述代码了。也就是说,这个方法会存在潜在的问题。
那我们是否可以使用我们刚刚所学的异或的方法来求解呐?
具体代码如下:
代码分析如图:
在实际操作中,我们要交换两个数的值时,我们大多数会使用第三变量法,因为上述的这种方法只适用于整数类型。
= 赋值操作符可以连续使用。如:a=x=y+1;首先将y+1的值赋给x,再将x的值赋给a。
但是,我们不建议这样写代码,这样的代码可读性和其他方面都不是很好。
复合赋值操作符:
+= 加等 a=a+5——>a+=5
-= 减等
*= 乘等
/= 除等
%= 取模等
>>= 右移等
<<= 左移等
&= 按位与等
|= 按位或等
^= 按位异或等
我们要分清楚初始化和赋值。
首先,初始化是指,在创建这个变量时为这个变量赋予一个初始值。
其次,赋值是指,在这个变量创建后,我们不想要这个初始值了,我们可以再为这个变量赋值为另一个我们想要的值。——>创建变量后,给它赋予一个新值。
具体见下图:
要注意:= —— >为赋值操作符
== ——> 用于测试“相等”
! 逻辑反操作
- 负值 ——>二进制的符号位(最高位)为1
+ 正值 ——>二进制的符号位(最高位)为0
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
首先,我们先要明白什么是单目操作符。a+b ——>这里的''+''是双目操作符——>操作符有两个操作数。那么我们可以知道,单目操作符就是说只有一个操作数的操作符叫单目操作符。
关于" !"
!——>按位取反。如果上述代码中的flag为真,那么!flag就为假。如果上述代码中的flag为假,那么!flag就为真。
C语言中,0表示假,非0表示真。
关于" & "
&叫做取地址操作符,它的作用就是取出一个变量在内存中的地址。
这个地址不是固定的。在每次程序运行时,程序都会为这个变量从新分配地址。
在上述代码中,&a取出的是a的首地址。(由于a是整型,占4个字节,每个字节有一个地址)
关于" sizeof "
sizeof的操作数就是它后面括号里面的数,如:sizeof(a)。此时,操作数就是a。
sizeof是一个操作符,计算的是变量所占内存空间的大小。也可以解释为:计算类型所创建变量占据空间的大小。单位全是字节。
类型是不占空间的。类型所创建的变量才占据空间。
sizeof(数组名)——>计算的是整个数组的大小,单位是字节。
sizeof后面跟的括号是可以去掉的,这样子也能够成立——>sizeof是操作符。
我们可以写成sizeof a;但是不可以写成sizeof int;
sizeof是操作符,不是函数。
strlen是库函数,是用来求字符串长度的。
指针不论是什么类型,它的大小都是4或8个字节。
关于" ~ "
对一个数的二进制按位取反。按位取反是对二进制的所有位都取反,包括我们的符号位。
上述代码的解释:
在这里,小刘同学向大家提出一个小问题:
题目如上图所示,要求我们编写代码使图中所示位置的0转变为1。该如何做呢?大家可以根据我们上面所讲的内容好好思考一下。
那么,下面小刘同学就为大家讲述一下该题的解题过程。
通过上面的小测试,我们可以引申出其他的修改二进制上某一位的题目。这里,小刘就不做多表述,但是,大家可以自己尝试一下哟。
关于" -- "
前置 -- :先--再使用
后置 -- :先使用再--
这样子去描述前置--和后置--的区别大家可能不能理解,那么,我们下面就来举一个例子吧:
关于" ++ "
前置 ++ :先++再使用
后置 ++ :先使用再++
与我们解释--的时候相似,我们首先来举一个例子来帮助理解一下我们的++操作符:
关于" * "
对于解引用操作符,我们一般和指针配合着去使用:
关于强制类型转换
关于这一操作符,我们先来举一个例子吧:
意思是说:3.14是double类型,而我们的a为int类型。如果将一个double类型的数赋给一个int类型的变量,我们的编译器会发出警告。如果,我们不想要看到这个警告,那么我们将进行下面的操作:
我们将3.14强制类型转化为整型。此时,a=3。double类型强制转化为int类型,就是说将double类型的小数去掉只要整数的部分。
>
> =
<
< =
! = 用于测试“不相等”
= = 用于测试“相等”
要注意“==”不是“=”
两个字符串相不相等不能简单的用==来比较——>这样比较是在比较它们的地址
两个字符串比较相不相等应该使用:strcmp库函数来比较。
&& 逻辑与 两个操作数都满足条件结果为1,否则结果为0。
|| 逻辑或 两个操作数只要有一个满足条件结果就为1,如果都不满足条件,结果为0。
要注意区分逻辑与和按位与;逻辑或和按位或。
举个例子吧!
1&&2——>1
1&2——>0
1||2——>1
1|2——>3
exp1?exp2:exp3
上述操作符的意思是指:如果exp1成立,那么执行exp2。如果exp1不成立,那么执行exp3。
例如:
a>5不成立,执行语句3——>b=7;
注意:不建议三目操作符写的过于复杂。
exp1,exp2,exp3,exp4,...... ,expn
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
例如:
1. [ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
2. ( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
3. 访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
下标引用操作符:
int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符。
[ ]的两个操作数是arr和9。——>arr[7] = 7[arr]
函数调用操作符:
函数调用操作符是不能省略掉的。
上述代码的操作数为:函数名,参数。
函数在调用的时候,它的操作数至少是一个。
访问结构体成员:
. 结构体.成员名
-> 结构体指针->成员名
无论是使用哪种方法都要注意传参!!!!!
创作不易,请大家多多支持!!!如有不懂的内容或者是小刘同学出错的内容,可以私信小刘同学哟~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。