操作符分类:
1.算术操作符
2.移位操作符
3.位操作符
4.赋值操作符
5.单目操作符
6.关系操作符
7.逻辑操作符
8.条件操作符
9.逗号操作符
10.下标引用,函数调用和结构成员
1.算术操作符 + - * / %
其中 + - * 较为简单,在这里不做过多的说明,而 / %有需要注意的几点
/ 除号操作符
/的两端如果都是整数,执行整数除法,例如7/2=3,而若其中一端是浮点数,则执行浮点数除法,例如1/2.0=0.5
注意:进行除法运算时分母不能为0,否则编译会出现错误
% 取余操作符
%两端的操作数必须是整数,返回的是整除后的余数
注意:除了%外,其他几个操作符均可应用于整数和浮点数的运算
2.移位操作符
<< 左移操作符
>> 右移操作符
<< 左移操作符规则:左边抛弃,右边补0
这里做一个小小的补充:
{
整数的二进制位有三种表示形式:原码,反码,补码
正整数的原码,反码,补码是相同的
负整数的原码,补码,反码是要计算的
}
详细解释请看代码段中的注释
当a为正:
#include<stdio.h>
int main()
{
//a为正数
int a = 5;
int b = a << 1;
//左移 移动的其实是存储在内存中的二进制位的补码
//先取a的二进制位如下
//00000000000000000000000000000101-原码/补码/反码
//原码最高位为符号位,0为正,1为负
//内存中存储的是补码
//根据左移规则进行左移操作后,得到的二进制位如下
//00000000000000000000000000001010
//所以b=10
//而因为这时候左移操作符只是一个效果,就跟加减乘除一样
//所以a不变,仍然为5
printf("%d %d\n", a, b);
return 0;
}
当a为负:
int main()
{
//a为负数
int a = -1;
//a的原码为
//10000000000000000000000000000001 - 原码
//原码的符号位不变,其他位按位取反,得到的就是反码
//11111111111111111111111111111110 - 反码
//反码+1得到补码
//11111111111111111111111111111111 - 补码
//所以a在内存中存储的是以上补码
int b = a << 1;
//左移操作后
//11111111111111111111111111111110 - 补码
//11111111111111111111111111111101 - 反码(补码减一得到反码)
//10000000000000000000000000000010 - 原码(反码取反得到原码,符号位不变,剩余位取反)
printf("%d\n", b);//b=-2
return 0;
}
注意:左移有×2的效果!
>> 右移操作符
int main()
{
//右移操作符
int a = 5;
int b = a >> 1;
printf("%d\n", b);
//右移操作符分两种
//1.算术右移
// 右边丢弃,左边补原来的符号位
//2.逻辑右移
// 右边丢弃,左边补0
//当前编译器采用的是算术右移,正数看不出差别,若用负数测试可知是算术右移,这里不再详细说明
return 0;
}
当前编译器(vs2013)采用的是算术右移(右边丢弃,左边补原来的符号位)
注意:算术右移有➗2的效果!
警告:对于移位运算符,不要移动负数位,这在c语言标准中是未定义的!
例如
int num = 10;
num>>-1;//error
3.位操作符(注意:它们的操作数必须是整数!)
位操作符有:
& 按位与
| 按位或
^ 按位异或
& 按位与
int main()
{
int a = 3;
int b = 5;
int c = a&b;//将a与b按位与后的结果存入c中
//按位与 其实是 按(2进制)位与
//简言之,有0为0,同1为1
//00000000000000000000000000000011 - a的二进制位
//00000000000000000000000000000101 - b的二进制位
//按位与后的结果是
//00000000000000000000000000000001 - c的二进制位
printf("%d\n", c);//c=1(二进制位转化成十进制位)
return 0;
}
| 按位或
int main()
{
int a = 3;
int b = 5;
int c = a|b;//按(2进制)位或
//简言之,有1为1,同0为0
//00000000000000000000000000000011 - a的二进制位
//00000000000000000000000000000101 - b的二进制位
//按位或后的结果是
//00000000000000000000000000000111 - c的二进制位
printf("%d\n", c);//c=7(二进制位转化成十进制位)
return 0;
}
^ 按位异或
int main()
{
int a = 3;
int b = 5;
int c = a^b;//按(2进制)位异或
//简言之,相同为0,相异为1
//00000000000000000000000000000011 - a的二进制位
//00000000000000000000000000000101 - b的二进制位
//按位异或后的结果是
//00000000000000000000000000000110 - c的二进制位
printf("%d\n", c);//c=6(二进制位转化成十进制位)
return 0;
}
异或的一个应用:在不使用第三变量,且不会溢出的情况下交换两个数字
int main()
{
int a = 3;
int b = 5;
a = a^b;//a与b先异或得到的称为密码,存在a中
b = a^b;//密码与b异或得到原a,存在b中
a = a^b;//密码与已经存在b中的原a异或得到原b,存在a中
printf("%d %d\n", a, b);//5 3
return 0;
}
右移操作符结合按位与操作符可以求出一个整数的二进制有多少个1(用整数的二进制位与上1的二进制位,然后右移)(这里先挖个坑,有空再填)
4.赋值操作符
+= a=a+10 等价于 a+=10
-=
*=
/=
%=
>>= a=a>>1 a>>=1
<<=
^= a=a^4 a^=4
|=
&=
赋值操作符较为简单,不做过多说明
5.单目操作符
! 逻辑反操作
+ 正值
- 负值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
操作符sizeof需要注意的一点
int main()
{
short s = 3;
int a = 10;
printf("%d\n", sizeof(s = a + 5));//2
printf("%d\n", s);//3
return 0;
}
sizeof里的表达式只在编译时候执行,也就是说在编译的时候第一个printf的逗号后面的值已经换成2了,在程序运行的时候sizeof已经不存在了。
所以要注意的是,sizeof里表达式是不参与运算的!!!
~ 取反操作符
int main()
{
int a = 0;
// ~ 按(二进制)位取反
//00000000000000000000000000000000
//11111111111111111111111111111111 - (取反后)在内存中以补码的形式存储
//而打印在屏幕上的是原码,原码取反+1得到补码
//所以补码-1取反得到原码
//10000000000000000000000000000001 - 原码
//打印出的值是原码对应的值
printf("%d\n", ~a);//-1
return 0;
}
++和--操作符
分为前置和后置,以++为例
b=++a 前置++,先++,再使用
b=a++ 后置++,先使用,后++
6.关系操作符
此操作符较为简单,不做详细说明
7.逻辑操作符
&& 逻辑与
|| 逻辑或
&& 逻辑与
int main()
{
int a = 3;
int b = 4;
int c = a&&b;//&& - 逻辑与 - 可以理解为 且
//当a和b都为真时,c才为真,若a和b存在假,则c为假
printf("%d\n", c);//1
return 0;
}
需要注意的是,对于逻辑与操作符,左边如果为假,右边不再计算!
例题:
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++&&++b&&d++;
printf("%d %d %d %d\n", a, b, c, d);//1 2 3 4
printf("%d\n", i);//0
return 0;
}
|| 逻辑或
int main()
{
int a = 0;
int b = 4;
int c = a||b;//|| - 逻辑或 - 可以理解为 或
//当a和b存在真时,c为真,当a和b都为假,c才为假
printf("%d\n", c);//1
return 0;
}
需要注意的是,对于逻辑或操作符,左边如果为真,右边不再计算!
8.条件操作符(三目操作符)
举例如下,较为简单,不做过多说明
int main()
{
int a = 4;
int b = a > 5 ? 3 : -3;
printf("%d\n", b);//-3
return 0;
}
9.逗号操作符
exp1,exp2,exp3...expN
逗号表达式,就是用逗号隔开的多个表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果
举例如下
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
printf("%d\n", c);//13
return 0;
}
10.下标引用,函数调用和结构成员
arr[4]=5 - [] - 下标引用操作符
调用函数时的括号()为函数调用操作符,表明这是一个函数,函数使用时一定带括号,像sizeof,使用的时候可以没有括号,所以sizeof不是一个函数
结构成员访问操作符 - 建立在结构体之上 . ->(箭头的左边时结构体指针变量)