各位看官们好,这是鄙人的第9篇博客了,这次我们来了解C语言中的操作符。虽然我们在前面的博客中已经提到过一些操作符了,这里我们来详细的写出C语言中的操作符了,并且新春之际,鄙人在这祝各位看官新年快乐!
算数操作符
算数操作符:这是我们在学习C语言的时候最早接触的了,首先就是‘+’ (加)‘-’(减)。这两个操作符,和我们在学习数学的是使用方法一样,在这,鄙人就不多赘述了。我们在在里主要讲一下‘/’(除)和‘%’(模)。
算数操作符:/
'/'除号是就计算除的数,如5/2结果是2。
但是我们都知道,5除以2结果为2.5。那么我们如何将5除以2的结果完整的打印出来呢?
首先我们需要将接收的类型改变,因为如果还是int类型的话,我们无论如何打印结果,依旧会是2.所以我们首先将int类型改为double类型(当然float类型也是可以的)。接着在除号的左右将被除数或者除号其中一个数改为小数,只需要一个就可以了。最后就是打印将“%d”改为“%lf”。这样我们就可以想上图一样,将小数打印出来。
算数操作符:%
%(模操作符)就是计算余数。如5%2结果就为1
虽然单个“%”大家看起来作用不是很大,但是我们可以与“/”一起使用,如我们将一个数值,分别打印出来。虽然我们这里是倒着打印的,但是想要打印出复合我们习惯的话,使用递归方法可以实现,这个我们后面会讲的。
注:%算数操作符只能是整数型
移位操作符
大家可以从名字上看到,移位操作符的作用就是将一个数字的位置进行改变,但是移位操作符改变的数的二进制。并且大家都知道除了0,剩下的都可以笼统的分为正数和负数。当负数存储在内存中需要将数值转换为二进制形式的补码(方法就是,将数值装换为二进制后这叫做原码。符号位不变,其余各位取反,则得到这个数字的反码。反码加1这样就是补码了),当然这是负数装换为补码的方法,要是正数的话就很简单了,只需要将数值转换为二进制就可以了。
右移操作符:>>
右移操作符,有两种右移,算数右移和逻辑右移。这两种右移有哪些区别呢?
大家可以看到上面的这个图片,我们将a(1000000000000000000000000000001)向右位移了一位,那么将最右边的1,变为了0。那么为什么还是-1呢。那么这就是“算数右移”:最右边的丢弃,然后最左边用符号位补齐。正数用0补。负数用1补。“逻辑右移”:右边丢弃,左边0补齐。这个鄙人暂时不知道如何向大家展示,因为在我们常见的系统中大多都是算数右移。并且右移有除2的效果。
左移操作符:<<
左移操作符就没有右移操作符的逻辑与算法的区别了,左移操作符只有逻辑左移,用0来补充。别去,右移有除2的效果,那么左移岂不是有乘2的效果了。没错,左移有乘2的效果
注:位移操作符,移动的话只能是正数,不能是负数。如a>>-1。这个是系统没有录进去的。反正就是位移只能是正数,如果是负数的话系统会出现一个和预料完全不一样的值。
位操作符
位操作符,大家也可以从名字中看到,我们操作的对象是每一位吧。当然这也是二进制位的数。
位操作符:&
这个符号大家应该不是很陌生吧,这是“与”操作符。我将它的作用总结为:相同为同,不同为0
这样大家可以很清楚的看到10与3的二进制补码相与后只有向右的第2位是两个1,所以想与后结果为2。
位操作符:|
这个是“或”操作符:有1为1,两0为0
这里大家可以看到或操作符的使用方法了吧。
位操作符:^
这个大家可要区分我们平常使用的符号是有区别的。这C语言中这个叫着“异或”。效果:相同为0,不同为1。
这大家看出来了吧。我们这里还有一个经典案例,对于使用“^”。将两个常量交换数值。
这个方法是我们简单的交换两个数值。将两个数相加后在减可以的出值
接下来就是"^"异或操作符的方法,虽然大家看这样与上面的这个区别不大呀,但这也是一个方法嘛,并且据我所知,在一个公司的笔试中曾经出过这么一道题。并且就要求使用异或的方法。大家多记得方法,对我们是有好处的。
赋值操作符
赋值操作符 "="可以改变原有的值。就是相当于你不满意以前的值,把以前的值改成自己满意的值。
直接赋值:=
像以前我们直接给常量赋值的话,那就是我们说是直接赋值。
连续赋值
就是我们连续使用赋值操作符"="。
这样读起来,就是将7+1赋给了x,然后又将x赋给了a。虽然大家看起来这样比较简洁,但是大家想一下这样看是不是很难看呀。虽然这里只有两个赋值操作符,但是后面的计算肯定更加多,那岂不是很长一串。所以不是很推荐大家使用连续赋值,因为可读性比较差,并且容易将自己给绕进去。
复合操作符
复合操作符大家可以在名字上看出来,是粘合在一起的,那么是那些粘合在一起的呢?是我们在上面将的各种操作符后加一个赋值操作符,那么就是复合操作符了。
复合操作符:+=
大家可以先看“+=”表面上看到,这个操作符是由一个“+”和“=”组成那么这个操作符如何使用呢?我们可以先看下面的图片来了解。首先是我们不使用“+=”操作符的情况。
这两张图片相比较来看,首先结果无差,并且下面的图片比上面的更加简洁。这个就是复合操作符的使用方法,其实就是省略了一个操作数,让表达式看起来更加简洁。
复合操作符:/=
了解了“+=”那么其他的复合操作符应该也都能知道如何使用了吧,那么我们在举一个例子“/=”。来使自己的思考得到验证。
这样大家可以看出吧,a=a/2与a/=2是一样的效果并且更为简洁。当然其他的复合操作符也是一样的。
单目操作符
这个操作符在鄙人前面的文章也有提及过,就是操作数只有一个的,叫做单目操作符。
单目操作符:!
这个“!”被称为逻辑反操作。把不为0的数变为0,为0的数变为1。下图就是将不为0的数(10)装换赋给a。
单目操作符:~
这个波浪号大家应该了解的不多吧。这个叫二进制取反操作符,所有的值都要变,但是得到的二进制是补码,需要将补码变成原码,才是真正的值)。可以在改变一个数的二进制情况下有作用
因为0的二进制全身0,那么取反0的话,得到的值就全为1,符号位也改变。但是因为取反后的值为原码,并且我们知道存储在系统中的二进制都是补码,那么将二进制改变后就为-1了。
单目操作符:- ,+
大家看这个可不要以为这是加与减呀。这个是正负号。那么大家应该知道它的作用了吧。“-”(负号)改变数值的正负型,当然“+”(正号)也是有改变正负型的效果,但只能由负变正,不能由正变负,并且我们一般会省略“+”号。
单目操作符:&,*
取地址操作符大家应该不陌生吧,我在一起的博客中有一部分提及过。“&”取地址操作符对于传址是很重要的。对于直接写一个子程序,想要改变主程序中的数组,就必须传址,那么我们这里就在举一个例子。
上图中先创建数组arr,然后将arr的地址传给子程序xixi中,并且赋值打印。
并且我们在子程序接收数组的时候使用了解引用操作符“*”,那么在这里也将解引用操作符一并解释掉。我们在主函数给xixi传址的时候引用了arr的地址,有引用那么就需要解引用,所以在接收地址的时候需要解引用。对于多级引用的话那么就要多几个解引用操作符。
单目操作符 :--,++
这个大家应该也不陌生吧,加加,减减。使用起来有前置加加和后置加加。前置减减和后置减减。因为“--”和“++”除了一个是加一个是减外,前置和后置是一样的那么我们就将其中一个。另外一个也是相同效果,就不多赘述了。
这里大家可以看到都是“++”但是一个打印的时候“1”,另外一个是“0”,并且打印“0”的时候a值明明为“1”呀。那为什么会是这样呢?这里我简单的理解就是。前置加加:先加后使用。后置加加:先用后加。这应该很容易理解吧。那么前置减减与后置减减应该也了解了吧。
单目操作符:(类型强制转换)
这个大家操作符大家在学习c语言的前期应该听的比较少吧。但是类型这个应该是每天都有使用的。那么这个操作符就是将一个类型装换为另外一个自己需要的类型。如
我们创建了一个float类型常量f且赋值为5.75.但是打印的时候我们将一个打印值强转为int类型。这样大家就知道强转类型装换的作用了吧。但是在还不熟练使用强转类型装换时,我们需要注意,不要将强壮装换的类型写在了()外面。如:
这是在还不熟练使用强制转换的时候容易出现的错误,大家需要注意,不要将强壮装换的类型写在()外。
单目操作符:sizeof
接下来是今天讲的单目操作符中的最后一个,也是记忆点较多的一个操作符。sizoef:可计算数组空间所以的大小。我们需要与strlen,区分一下,不要混淆了,strlen的作用是计算\0之前的大小。后面类型不能将()省略掉如sizeof int是错误的.sizeof括号里面的计算是不会影响实际值的。如sizeof(s=1+2)
这里我们在arr数组里面放置了6个元素,用sizoef计算数组arr的大小,且arr是int类型数组,那么数组arr的大小为4*6.那么打印出来的值为24。
这里我们需要注意不要将sizeof后的()有时候可以剩余掉,比如上面这个常量,但是,如果计算类型呢?
这样我们就知道在计算类型大小的时候不能将()省略掉。 计算数组或者常量的时候可以。
接着计算sizoef计算不会影响实际值如:
我们可以看到第二个printf中我们写的时候sizeof(a=7+1),计算出得结果为4,这是没错的,因为我们在创建a的时候就是int类型,那么计算出结果为4。但是下一个打印a 的值时,a却没有改变那么我们可以得知,在sizeof中的计算是不会改变实际值的,只会影响当场sizoef的计算结果。
关系操作符
关系操作符其实就是比较大小如:> < <= >= ==这些都是关系操作符,相对于的话就是<= 和>=是较有难度的,我们就挑一个来解释。
关系操作符:>=
我们可以看到这个关系操作符前半部分是“>”,那么我们解读就是“大于等于”。
我们可以在a为5的时候及时停下来,但如果仅仅是“>”的话就要向前冲一点,才停下来。
那么"<="大家应该也了解了吧。
逻辑操作符
逻辑操作符中只有两个小操作符逻辑与(&&) 逻辑或(||)。逻辑与和与操作的区别是,逻辑与返回值只有1或0,两个都为真返回1,不是的话返回0。逻辑或效果差不多,只有要都为假,才返回0。
逻辑操作符:&&
在逻辑与中常常有多个计算式但是只要左边的为假,后面的就不用计算了如:
因为在逻辑与操作符中第一个表达式就为假,那么只有一个a++执行了,后面的表达式直接跳过。所以这是逻辑与的使用方法。
逻辑操作符:||
逻辑或操作符就与逻辑与是对立的了,逻辑或的是左边为真,后面就不会在计算了。如:
在这个表达式中a为0,则可以继续执行,但是b的初值为1,为真,所以就不会在向后执行。
三目操作符(条件操作符)
三目操作符这个就比较简单了,“exp1?exp2 :exp3” 这里大家需要注意其中的符号是确定的不能改变的。 a>b? a:b a>b为真,执行后面的a,a>b为假执行b
这里可以看到了吧因为a>b为假,所以执行后面的那个指令将-1赋给了c 。也可以在while循环中使用。
逗号表达式
这个大家应该也有印象吧,(a,b,c,d,e)这样叫逗号表达式,依次从左向右执行,结果为最后的那个结果。
我们可以看到yy的值为11了,所以这验证了逗号表达式的结果为最后的那个结果。但是在括号中的其他表达式也执行了。大家可以在自己尝试的时候调试看,其他值是否有改变。
下标引用操作符
下标引用操作符[]:一个数组名+一个下标值。如int arr[10]={0};arr[4]=5;arr计算数组名,4就是下标值
函数调用操作符
函数调用操作符():xixi(a,b)xixi是操作数的函数名,()里面的是参数,可以是一个也可以是多个
访问结构体成员
访问结构体有两种方法一个是:结构体.成员 ,另一个是:结构体->成员名。那么他们使用有哪些区别呢?
结构体.成员
这样是不是我们在打印结构体内容的时候就是“结构体.成员”。
结构体->成员名
我们这里在给结构体xixi确定,内容后用 “结构体->成员名”打印出姓名和年龄。这样大家了解了访问结构体成员的两种方法了吧。
以上就是鄙人今天想与大家分享的知识了,肯定还有很多不足的地方,而且写的时候在过年期间有点心猿意马了,所以希望大家可以在评论区写出来,以便改正