操作符详解
大家好,我是晓星航。今天为大家带来的是关于操作符的讲解!😀
1.1操作符的分类
算术操作符
移位操作符
位操作符
赋值操作符
单目操作符
关系操作符
逻辑操作符
条件操作符
逗号表达式下标引用、函数调用和结构成员
2.1算术操作符:+ - * / %
1.除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
2.对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3.% 操作符的两个操作数必须为整数。返回的是整除之后的余数。
3.1移位操作符:<< 左移操作符 >> 右移操作符
注:移位操作符的操作数只能是整数,且位移的是地址。
左移操作符例子如下:
这里将a的地址整体向右移动了两位,从而得到了b。
右移操作符:
1.算术右移**(右边丢弃,左边补原来的符号位)**
2.逻辑右移**(右边丢弃,左边补0)**
到底右移是算术还是逻辑右移,取决于编译器的~
我们常见的编译器下都是算术右移
右移操作符例子如下:
3.1.2正数和负数的原码反码补码的解释
整数在内存中存储的是补码。
4.1位操作符:
4.1.1按位与:&(2进制)----两个代码同时为1才为1,一个0一个1为0.(只要有0则为0)
这里我们给一个例题展示(解答过程在图上!):
4.2.1按位或:|(2进制)----两个代码同时为0才为0,一个0一个1为1.(只要有1则为1)
这里我们给一个例题展示(解答过程在图上!):
4.3.1按位异或 :^ (二进制)----两个代码相同为0,相异为1.
这里我们给一个例题展示(解答过程在图上!):
4.3.2异或小规律:
1.:0异或n = n;
2.:n异或n = 0;
通过以上运算符的学习后这里给大家一道变态的面试题:不能创建临时变量(第三个变量),实现两个数的交换。
刚看到这个大家肯定都懵😵了,但在我们学习了异或操作符后我们其实是可以实现它的。
连续用了两次异或的规律,aa=0,bb=0,0a=a,0b=b.多么巧妙地解法啊!😆
4.3.3异或的作用:
如果没有异或的化,想改变一个数中的某个地址(0改为1,1改为0)可是十分难得呢。
5.1.1赋值操作符:
这里的a = x;
x = y + 1;
注意:左值,是可以放在等号左边的,一般是一块空间
右值,是可以放在等号右边的,一般是一个值,或者一块空间的内容
例如:
a = x; 中的a为左值(空间),x为右值(值)。
x = y + 1;中的x为左值(空间),y为右值(值)。
*5.2.1复合赋值符:+= -= = /= %= >>= <<= &= |= ^=
eg:
int x = 10;
x = x+10;
x += 10;
6.1.1单目操作符:
! 逻辑反操作 - 负值
+ 正值 & 取地址
sizeof 操作数的类型长度(以字节为单位) ~ 对一个数的二进制按位取反
–前置、后置-- ++前置、后置++
* 间接访问操作符(解引用操作符) (类型) 强制类型转换
这里我们挑几个重点操作符进行讲解:
1.:!(逻辑反操作) :
!将假变为真,真变为假。
2.:~ (对一个数的二进制按位取反) :
用法:要求将 00000000000000000000000000001110
变为 00000000000000000000000000001010
~的用法便是得到一个除了我们所需的0其余全为1的那个二进制数。
3.:++a和a++的区别:
++a是先加加后使用,a++是先使用后加加。
–a是先减减后使用, a–是先使用后减减。
4.:间接访问操作符(解引用操作符):
注意*可以与指针联系起来哦。
5.:(类型) 强制类型转换
此时a从一个浮点数3.14转化为了一个整形3.
6.2.1sizeof和数组:
下面为用sizeof计算数组的大小:
注意:指针的大小在32位下位4个字节,在64位下为8个字节。指针的大小和变量类型无关系,一定为4个字节或8个字节!!!
seizeof和strlen区分:
strlen是一个库函数,计算的是字符串的长度,并且只能针对字符串,关注的是字符串中是否有\0,计算的是\0之前的字符个数 针对长度
sizeof是一个操作符(运算符),是用来计算变量所占内存空间大小的,任何类型都可以使用,只关注空间大小,不在乎内存中是否存在\0 针对内存大小,sizeof单位是字节
6.2.2数组,字符串等哪些有\0结尾:
对于整数型数组来说,结尾字符为整数
对于字符型数组来说,结尾字符为\0,占一个空间。但总个数还是以char arr[n]中n的个数为准。 eg:char arr[10] 中可以放九个字符,最后一个必须为’\0’,因为**\0是字符数组结束的标志**,不然会陷入死循环。
字符串结尾也会有\0作为结束标志。
所以当输出字符串数组时,若要整体输出(printf(“%s”,s)),则要在数组末尾添上\0,否则会将数组后面未定义的空间也输出
7.1.1关系操作符
> >=
< <=
! = 用于测试“不相等”
== 用于测试“相等”(判断相等)
a == 5;写为5 == a; 可以减少编程错误,如果误写成5 = a;则程序会报错。
注:一个=为赋值,两个==才为判断。
8.1.1逻辑操作符
&& 逻辑与(全真则真,一假则假)
|| 逻辑或 (全假为假,一真为真)
用法:0&&1=0 0||1=1
要求输出:00 && a<18
一道360的笔试题:
我一开始算的结果:a=1,b=3,c=3,d=5;
实际结果:a=1,b=2,c=3,d=4;
解题过程如上。对于且(&&)来说只要算到0(假)则后面的逻辑均不算。
如果将a改为1:
则表达式正常运行。
对于或(||)来说只要算到1(真)则后面逻辑均不算。
将&&改为||运行结果如下:
当题目算到a=1时,发现1||a表达式或恒为真,后面的运算失效。所以除a之外其余值全部不变化。
总结:&& - 左操作数为假,右边不计算。
|| - 左操作数为真,右边不计算。
9.1.1 条件操作符(三目操作符)
格式:表达式1?表达式2:表达式3;
上述例子意为:a大于b吗,如果大于输出a,如果不大于输出b。
10.1.1逗号表达式
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
11.1下标引用、函数调用和结构成员
11.1.1. [ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
eg:int arr[10];//创建数组
arr[9] = 10;//实用下标引用操作符。
arr[7]—>(arr+7)—>(7+arr)—>7[arr] 最终打印的结果均相同。
11.1.2. ( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
基本形式: 函数(); ----括号中放入要传的参数。
11.1.3.访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
12.1表达式求值
12.1.1隐式类型转换
整型提升:C的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型。
整型提升的意义:
如何整型提升?
整形提升是按照变量的数据类型的符号位来提升的
char类型只能存8个比特位
提升之后还是补码,如果为%d----整形输出的话要转化为原码。负数:补码-1=反码,反码按位取反=原码。
12.2.1 算术转换
**寻常算术转换:**如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。
规则:下面的类型往上面转化!!!
eg:
拓展:1:表达式有两个属性:值属性,类型属性。
eg:int a = 10;
int b = 20;
a + b; //此时30为表达式的值属性,int为表达式的类型属性。
2:sizeof()括号内部的表达式不区真实计算的!
12.3.1 操作符的属性
复杂表达式的求值有三个影响的因素:
\1. 操作符的优先级
\2. 操作符的结合性
\3. 是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。
感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘