运算符详解

运算符

一、算数运算符

算数运算符有: + - * / % 五种。由于运算符有两个操作数。也被称为双目运算符

对于 / 运算符,两个操作数都是整数执行的是整数除法。至少有一个操作数是浮点时执行浮点除法

#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
上一篇:java String StringBuffer以及BtringBuilder


下一篇:ip,子网掩码,前缀