操作符分类:
🦎算术操作符
>> + - * / % <<
>>注意<<
- 除了 % 以外,其他操作符都可以作用于整数和浮点数。
- 对于 / 操作符如果两个数都是整数,执行整数除法。但是只要有一个数是浮点数,就执行小数除法。
- % 操作符的两个操作数必须是整数。返回的是整除之后的余数。
🐊位移操作符
这里我们来讲一下整数的二进制位的相关知识:
1)整数进制的表示:
- 我们以12为例
二进制: 00000000 00000000 00000000 00001100
八进制: 14
十进制: 12
十六进制: c
二进制中(从左往右数)第一位是符号位,若为1,则该数十进制数为负,反之;
>> 在十六进制中0 ~ 9之后,a ~ f 分别表示10 ~ 15 <<
2)进制的相互转化:
谈到进制转化,涉及到 权重问题
- 权重问题
- 基数
-数码的个数。比如二进制数的基数为2。十进制数的基数为10。十六进制数的基数为 16。- 位权
位即位置、权即是权重,数字中每一个位置对应的单位值称为位权,也就是不同进制里的“1”在不同的位置上所代表的值。
例如 十进制第2位的位权为101,第3位的位权为102;而二进制第2位的位权为21,第3位的位权为22。那么我们可以得出,某位置上的数码对应的值等于数码乘以位权。
可以这样去理解:位权是数码在某个位置上的步进,在不同位上步进大小不一样,高位大低位小。
- 我们还是以12为例
二进制转换为十进制:
这里只是简单介绍下,具体多进制转换方法,我会出一篇博客的,博客出来后,这里会有超链接直通车----->《 进制转换,详解》
三码(原码、反码、补码)
- 原码: 按照一个数的正负,直接写出它的二进制表示形式得到的就是原码
- 反码: 是原码的符号位不变,其他位按位取反,就是反码
- 补码: 是反码+1
- 正数
正数的原码、反码、补码是相同的- 负数
负数的原码、反码、补码要经过计算的
整型占4个字节(32bit)
- 正数
正数的原码、反码、补码是相同的
int a = 10;
00000000000000000000000000001010 - 原码
00000000000000000000000000001010 - 反码
00000000000000000000000000001010 - 补码
- 负数
负数的原码、反码、补码要经过计算的
int b = -10;
10000000000000000000000000001010 - 原码
11111111111111111111111111110101 - 反码
11111111111111111111111111110110 - 补码
负数三码转换:
>> 好了,接下来就开始进入位移操作符的介绍了<<
<< 左移操作符 >> 右移操作符
注意:
1.这里移动的是二进制位(补码);
2.移位操作符的操作数只能是整数;
<< 左移操作符
- 运算规则:
左边舍弃,右边不0;
a = 10; b = a << 1;
a << 1表示a的二进制数向左移动一位:
00000000000000000000000000001010 ------> 00000000000000000000000000010100
此时表达式a<<1就变成了20;但是a的值并没有发生任何变化。
- 右移效果
右移n位,就有原始值 / 2^n^ 的效果
🦖位操作符
位操作符:
& //按位与 >> 0是老大<<
| //按位或 >> 1是老大<<
^ //按位异或 >> 同0异1<<
注意:他们的操作数必须为整数。
这里我们就用代码来浅浅演示下吧
#include<stdio.h> int main() { int num1 = 1;//00000000 00000000 00000000 00000001 int num2 = 2;//00000000 00000000 00000000 00000010 printf("%d\n", num1 & num2); //按位与“0是老大”==“有0则0,两个为1才为1” //00000000 00000000 00000000 00000001 //00000000 00000000 00000000 00000010 //00000000 00000000 00000000 00000000 --->按位与后的结果0 printf("%d\n", num1 | num2); //按位或“1是老大”==“有1则1,两个为0才为0” //00000000 00000000 00000000 00000001 //00000000 00000000 00000000 00000010 //00000000 00000000 00000000 00000011 --->按位或后的结果3 printf("%d\n", num1 ^ num2); //按位异或 相同为0,相异为1; //00000000 00000000 00000000 00000001 //00000000 00000000 00000000 00000010 //00000000 00000000 00000000 00000011 --->按位异或后的结果3 return 0; }
好,这里我们再来看一道比较变态的面试题吧
题目要求:在不使用临时变量的条件下,完成两个数的交换。
- 解答过程:
#include<stdio.h> int main() { int a = 5, b = 3; a = a ^ b;----->a=a^b b = a ^ b;----->b=a^b=a^b^b=a a = a ^ b;----->a=a^b=a^b^a=b printf("a = %d b = %d", a, b); return 0; }
这里涉及到异或的一些结论:
- a^a=0;
- a^0=a;
- 异或是支持交换律的;
我们带着结论再回去看看是不是了解了。
· 这里也存在几个缺点:
a 只能用于整数交换
b 效率真的不太高
c 不容易读懂
所以它仅仅是面试官的特异照顾。。。。
🐲赋值操作符
赋值操作符我们想必已经相当了解了,所以这里我就浅浅介绍几下它的细节吧
- 连续赋值
a=x=y-1------>这种赋值重点考虑它的顺序——>从右至左。
- 复合赋值符:
+=
-=
*=
/=
%=
‘>>=’
<<=
&=
|=
^=
这些都存在复合的效果就拿其中一个举例子吧
+= ------->它表示的是先自加再赋值-----> a+=2---->a=a+2;
其他符号也是同理,这里就不过度赘述了
🐢单目操作符
! --------> 逻辑反操作
– -- -------->前置、后置-- –
++ -------->前置、后置+ +
& --------> 取地址
sizeof --------> 操作数的类型长度
星号* --------> 间接访问操作符(解引用操作符)
(类型) --------> 强制类型转换
讲解下sizeof吧
输入形式:
sizeof(a)
sizeof a ------>括号可去掉
sizeof(int)----->这里的括号不能去除
讲解下 – -- , + +吧
int a=10; int y=a++; int x=++a;
主要讲解前置和后置
++前置:
先使用a,再让a增加
---->所以这里y的值为10,a的值为11;
++后置
先让a增加,再使用a
---->所以这里x的值为11,a的值为11
🦖关系操作符
—> > -----------大于号
—> >= ---------大于等于号
—> < -----------小于号
—> <= ----------小于等于号
—> == ----------相等(等号)
—> != -----------不相等
这里重点注意敲代码过程中‘=’与‘= =’的区分
🐍逻辑操作符
&&------>逻辑与----->一假全假
|| ------>逻辑或----->一真全真
判断为真,整体值为1;
判断为假,整体值为0;
这里我们就举一个360面试题:
#include<stdio.h> int main() { int i = 0, a = 0, b = 2, c = 3, d = 4; i = a++ && ++b && d++; ------> 答案: 1 2 3 4 或许,大家看到这个大那有些惊讶。是的我也惊讶。我们来细细看一下吧 ------>这里是存在电脑短路(就是电脑很懒)a++先使用a=0;被判断为假,&&一假则假----->所以整体判断就一定是假了,所以就相当于把后面的表达式屏蔽了。 我们就知道了,&&,||,具有控制求值顺序的性质 //i = a++ && ++b && d++; ------> 答案: 1 3 3 4 printf("a = % d, b = % d, c = % d, d = % d", a, b, c, d); return 0; }
🦕条件操作符
- exp1?exp2:exp3
------>解析:exp1表达式1成立?
------>成立整体的值就是exp2的结果
------>否则就是exp3
逗号表达式
- 逗号表达式,就是用逗号隔开几个表达式。
从左向右依次运算。整体的结果为最后一个表达式的结果。
🐉下表引用、函数调用和结构成员
- []下标引用操作符:一个数组名+一个索引值;
- ()函数调用操作符:函数名+其余传给函数的参数;
- 访问一个结构的成员:
- 结构体-----自定义类型(聚合类型)
生活中有些对象要被描述出来的话,不能简单的实用内置类型表示。
. --------> 结构体.成员名
-> ------> 结构体指针->成员名
#include<stdio.h> struct Book { char name[20]; char auther[30]; int price; }; void print(struct Book* p) { printf("《%s》 %s %d", p->name, p->auther, p->price); //结构体指针->成员名 } int main() { struct Book b1 = { "高等数学","某某",99 }; printf("《%s》 %s %d\n", b1.name, b1.auther, b1.price); //结构体变量.成员名 print(&b1); }