操作符分类:
1.算术操作符
+ - * / %
1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数(取模只能用于整数)。
2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。
#include<stdio.h> int main() { //操作符(运算符) int ret1 = 10 / 3; 备注:对于除法操作符来说,两边的操作数都是整数,执行的是整数除法 如果想计算出小数,除号的两端至少有一个操作数是浮点数 double ret2 = 10.0 / 3.0; printf("%d\n", ret1); printf("%lf\n", ret2); printf("%.1lf\n", ret2);//%.lf表示保留小数点后一位 int ret3 = 10 % 3;//取模(取余),计算的是整除之后的余数,取模操作符的两边的操作数只能是整数 printf("%d\n", ret3); return 0; }
2.移位操作符
首先要提一下2进制整数的表示形式 :原码、反码、补码。
其中正数的原、反、补码相同。而负数的反码等于原码按位取反(符号位不变),补码=反码+1;
00000000000000000000000000001010 - 原码
00000000000000000000000000001010 - 反码
00000000000000000000000000001010 - 补码
int a = 10;//正数
10000000000000000000000000001010 - 原码
11111111111111111111111111110101 - 反码
11111111111111111111111111110110 - 补码
int b=-10;//负数
以下是原码,反码,补码的相互变换(针对的是负数)
(1)左移操作符:
左边抛弃、右边补0
num<<1的结果是移位之后的效果,但num的值是不变的
(2)右移操作符
分两种:
1. 逻辑移位 左边用0填充,右边丢弃
2. 算术移位 左边用原该值的符号位填充,右边丢弃
int a = -1;
原码:10000000000000000000000000000001
反码:11111111111111111111111111111110
补码:11111111111111111111111111111111
int b=a>>1;
逻辑移位左边最高位符号位都是补0,算术移位补原来该数值的符号位。
在计算机中移位是采取算术移位的
注意:
对于移位运算符,不要移动负数位,这个是标准未定义的。
int num = 10;
num>>-1;//error
3.位操作符
以下操作符均针对于二进制位进行计算的
& //按位与
| //按位或
^ //按位异或
注:他们的操作数必须是整数
(1)按位与
对应的二进制位有0,则为0,两个同时为1,才为1
注意都是转换成补码后才进行计算的
//& - 按2进制位与 //对应的二进制位有0,则为0,两个同时为1,才为1 int main() { int a = 3; //00000000000000000000000000000011 int b = -5; //10000000000000000000000000000101 //11111111111111111111111111111010 //11111111111111111111111111111011 -补码 int c = a & b; //00000000000000000000000000000011 //11111111111111111111111111111011 //00000000000000000000000000000011 printf("%d\n", c); return 0; }
(2)按位或
对应的二进制位有1则为1,两个同时为0则为0
//按2进制位或 //对应的二进制位有1则为1,两个同时为0则为0 int main() { int a = 3; //00000000000000000000000000000011 int b = -5; //10000000000000000000000000000101 //11111111111111111111111111111010 //11111111111111111111111111111011 -补码 // int c = a | b; //00000000000000000000000000000011 //11111111111111111111111111111011 //11111111111111111111111111111011 // printf("%d\n", c); return 0; }
(3)按位异或
对应的二进制位:相同为0,相异为1
//^ - 按2进制位异或 //对应的二进制位:相同为0,相异为1 int main() { int a = 3; //00000000000000000000000000000011 int b = -5; //10000000000000000000000000000101 //11111111111111111111111111111010 //11111111111111111111111111111011 -补码 // int c = a ^ b; //00000000000000000000000000000011 //11111111111111111111111111111011 //11111111111111111111111111111000 //11111111111111111111111111110111 //10000000000000000000000000001000 //-8 printf("%d\n", c); return 0; }
面试题:
不能创建临时变量(第三个变量),实现两个整数的交换
两种方法:
第一种
int main() { int a = 3; int b = 5; printf("%d %d\n", a, b); a = a + b; b = a - b; a = a - b; printf("%d %d\n", a, b); return 0; } //a=a+b; //b=a+b-b; //a=a+b-a;
但是a和b的数值太大会溢出,超出规定范围,有一定风险。
第二种
异或操作符:
1.a^a=0
2.0^a=a
3.异或是支持交换律的
#include<stdio.h> int main() { int a = 3; int b = 5; printf("交换前:"); printf("%d %d\n", a, b); a = a ^ b; b = a ^ b; a = a ^ b; printf("交换后:"); printf("%d %d\n", a, b); return 0; }
但是异或操作符交换2个变量也有缺点:
1.可读性差
2.效率也不如使用临时变量的方法
3.异或只能对整数的交换
4.赋值操作符
赋值操作符自右向左结合,也可以进行复合赋值,简化代码
int main()
{
int a = 10;
a = a + 5;
a += 5;
}
复合赋值符
+= -= *= /= %= >>= <<= &= |= ^=
连续赋值可以写成:
int a = 10;
int x = 0;
int y = 20;
a = x = y+1;//连续赋值
但这样写有缺点:
1.可能会让人产生困惑,到底是先把x值赋给a,再把y+1赋给x。还是先把y+1赋给x,再把x赋给a。(本质上是从右向左赋值)
2.不好调试
x = y+1;
a = x;//这样写更容易调试