运算符
一、算数运算符
算数运算符有: + - * / % 五种。由于运算符有两个操作数。也被称为双目运算符
对于 / 运算符,两个操作数都是整数执行的是整数除法。至少有一个操作数是浮点时执行浮点除法
#include <stdio.h>
int main() {
int i = 5 / 2;
printf("%d\n", i);
return 0;
}
输出
2
#include <stdio.h>
int main() {
double i = 5.0 / 2;
printf("%lf\n", i);
return 0;
}
输出
2.500000
%运算符的两个操作数必须为整数,返回的是整除后的余数
#include <stdio.h>
int main() {
int i = 20 % 6;
printf("%d\n", i);
return 0;
}
对于 a / b ,运算符两个操作数有一个是负数时。如果左操作数是负数,结果为:-((-a) / b)。如果右操作数是负数,结果为:-(a / (-b))
#include <stdio.h>
int main() {
int i = -7 / 3;
int j = 5 / -2;
printf("-7 / 3 = %d\n", i);
printf("5 / -2 = %d\n", j);
return 0;
}
输出
-7 / 3 = -2
5 / -2 = -2
对于 a % b ,运算符两个操作数有一个是负数时。如果左操作数是负数,结果为:-((-a) % b)。如果右操作数是负数,结果为:a % (-b)
#include <stdio.h>
int main() {
int i = -7 % 2;
int j = 5 % -2;
printf("-7 %% 2 = %d\n", i);
printf("5 %% -2 = %d\n", j);
return 0;
}
输出
-7 % 2 = -1
5 % -2 = 1
二、移位运算符
前言:整数在内存中存储的是二进制。存储有符号整数时将二进制最高位设定为符号位,1表示负数,0表示正数。一个整数二进制表示形式有原码、反码、补码。正整数的原码、反码、补码都相同。负整数的原码、反码、补码需要计算。使用、打印整数时使用原码,计算时使用补码
int i = 10; //正整数的原码、反码、补码都相同
00000000 00000000 00000000 00001010 //10的原码
00000000 00000000 00000000 00001010 //10的反码
00000000 00000000 00000000 00001010 //10的补码
int j = -1
10000000 00000000 00000000 00000001 //-1的原码,即将-1化为二进制,最高位用1表示负数
11111111 11111111 11111111 11111110 //-1的反码,符号位不变,原码其他位按位取反
11111111 11111111 11111111 11111111 //-1的补码,反码+1
2.1左移运算符 <<
用法: 数字 << n
对数字的补码向左边移动n位,即左边抛弃,右边补0
#include <stdio.h>
int main() {
int i = 10 << 2;
//00000000 00000000 00000000 00001001 原码
//00000000 00000000 00000000 00001001 反码
//00000000 00000000 00000000 00001001 补码
//00000000 00000000 00000000 00100100 对补码左移2位,右边补2个0
printf("%d\n", i);
return 0;
}
输出
40
#include <stdio.h>
int main() {
int i = -1 << 2;
//10000000 00000000 00000000 00000001 -1原码
//11111111 11111111 11111111 11111110 -1反码
//11111111 11111111 11111111 11111111 -1补码
//11111111 11111111 11111111 11111100 对补码左移2位,右边补2个0
//11111111 11111111 11111111 11111011 反码,对上面补码-1
//10000000 00000000 00000000 00000100 原码,对反码符号位不变,其他位按位取反
printf("%d\n", i);
return 0;
}
输出
-4
2.2 右移运算符 >>
用法:数字 >> n
对数字的补码右移n位,即右边抛弃,左边填充
根据填充规则分为两种:逻辑移位与算数移位
逻辑移位:左边用0填充
算数移位:左边用该数字符号位填充
大部分编译器使用的是算数移位。我们演示代码的编译器也是算术移位
#include <stdio.h>
int main() {
int i = -1 >> 2;
//10000000 00000000 00000000 00000001 -1原码
//11111111 11111111 11111111 11111110 -1反码
//11111111 11111111 11111111 11111111 -1补码
//11111111 11111111 11111111 11111111 对补码右移动2位,左边全部补符号位1
//计算后结果还是-1的补码,所以还原成原码不再写
printf("%d\n", i);
return 0;
}
输出
-1
#include <stdio.h>
int main() {
int i =10 >> 2;
//00000000 00000000 00000000 00001010 10原码
//00000000 00000000 00000000 00001010 10反码
//00000000 00000000 00000000 00001010 10补码
//00000000 00000000 00000000 00000010 对补码右移动2位,左边全部补符号位0
printf("%d\n", i);
return 0;
}
输出
2
对于移位运算符,不要移动负数位,这个是C语言标准未定义的
如 int i = 10 >> -1 ;
三、位运算符
位运算符有:按位与 & 按位或 | 按位异或 ^ 三种
3.1 按位与 &
用法: num1 & num2
将两个数的补码计算出来,两个数对应的二进位都为1时,结果为1,否则为0
#include <stdio.h>
int main() {
int i = 10 & -3;
//00000000 00000000 00000000 00001010 10 的原码、反码、补码
//10000000 00000000 00000000 00000011 -3 的原码
//11111111 11111111 11111111 11111100 -3 的反码
//11111111 11111111 11111111 11111101 -3 的补码
//00000000 00000000 00000000 00001010 10补码
//11111111 11111111 11111111 11111101 -3 补码
//00000000 00000000 00000000 00001000 对应二进制位都为1,结果为1,否则为0
printf("%d\n", i);
return 0;
}
输出
8
3.2 按位或 |
用法: num1 | num2
将两个数的补码计算出来,两个数对应的二进位至少有1个为1时,结果为1,否则为0
#include <stdio.h>
int main() {
int i = -4 | -3;
//10000000 00000000 00000000 00000100 -4 的原码
//11111111 11111111 11111111 11111011 -4 的反码
//11111111 11111111 11111111 11111100 -4 的补码
//10000000 00000000 00000000 00000011 -3 的原码
//11111111 11111111 11111111 11111100 -3 的反码
//11111111 11111111 11111111 11111101 -3 的补码
//11111111 11111111 11111111 11111100 -4补码
//11111111 11111111 11111111 11111101 -3 补码
//11111111 11111111 11111111 11111101 对应二进制位至少1个为1时,结果为1,否则为0 (此结果为补码)
//11111111 11111111 11111111 11111100 反码,补码-1
//10000000 00000000 00000000 00000011 原码,反码符号位不变,其他位按位取反
printf("%d\n", i);
return 0;
}
输出
-3
3.3 按位异或 ^
用法: num1 ^ num2
将两个数的补码计算出来,两个数对应的二进位相同时,结果为0,否则为1
#include <stdio.h>
int main() {
int i = -4 ^ -3;
//10000000 00000000 00000000 00000100 -4 的原码
//11111111 11111111 11111111 11111011 -4 的反码
//11111111 11111111 11111111 11111100 -4 的补码
//10000000 00000000 00000000 00000011 -3 的原码
//11111111 11111111 11111111 11111100 -3 的反码
//11111111 11111111 11111111 11111101 -3 的补码
//11111111 11111111 11111111 11111100 -4补码
//11111111 11111111 11111111 11111101 -3 补码
//00000000 00000000 00000000 00000001 对应二进制位相同时,结果为0,否则为1
printf("%d\n", i);
return 0;
}
输出
1
3.4 经典笔试题
题目:有两个整数类型变量a、b,不创建临时变量交换a与b的值
方法一
#include <stdio.h>
//当两个数相加和大于int类型时,存在溢出,此方法就不能使用
int main() {
int a = 10;
int b = 20;
printf("交换前 a = %d b = %d\n",a,b);
a = a + b;
b = a - b;
a = a - b;
printf("交换后 a = %d b = %d\n", a, b);
return 0;
}
输出
交换前 a = 10 b = 20
交换后 a = 20 b = 10
方法二
#include <stdio.h>
int main() { //此方法只适用两个整数之间交换
int a = 10;
int b = 20;
printf("交换前 a = %d b = %d\n",a,b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("交换前 a = %d b = %d\n", a, b);
return 0;
}
输出
交换前 a = 10 b = 20
交换前 a = 20 b = 10