目录
  • 前言
  • 1、操作符的分类
  • 2、算术操作符
  • 3、移位操作符
    • 3.1 左移操作符
      • 3.1.1 正数左移1位
      • 3.1.2 负数左移1位
    • 3.2 右移操作符
      • 3.2.1 正数右移1位
      • 3.2.2 负数右移1位
    • 3.3 移位操作符说明
    • 4、位操作符
      • 4.1 练习 1
        • 4.2 练习 2
        • 总结

          前言

          操作符主要内容包括:各种操作符的介绍,用表达式求值。

          1、操作符的分类

          • 算术操作符
          • 移位操作符
          • 位操作符
          • 赋值操作符
          • 单目操作符
          • 关系操作符
          • 逻辑操作符
          • 条件操作符
          • 逗号表达式
          • 下标引用、函数调用和结构成员

          2、算术操作符

           +  -  *  /  %  (加法 减法 乘法 取余 取模)
          
          int main()
          {
          	int a = 9 / 2;//4
          	float b = 9 / 2;
          	int c = 9.0 / 2;
          	float d = 9.0 / 2;//4.5
          	float e = (float)9.0 / 2;
          
          	printf("%d\n", a);
          	printf("%f\n", b);
          	printf("%d\n", c);
          	printf("%f\n", d);
          	printf("%f\n", e);
          	return 0;
          }
          

          运行结果见下图:

          C语言操作符超详细讲解上篇

          C语言操作符超详细讲解上篇

          C语言操作符超详细讲解上篇

          通过例子可发现,变量的类型使用错误的话,结果也是错误的

          • 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数
          • 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法
          • % 操作符的两个操作数必须为整数。返回的是整除之后的余数

          3、移位操作符

          移位操作符的操作数只能是整数

          << 左移操作符
          >> 右移操作符

          3.1 左移操作符

          • 移位规则:左边抛弃、右边补0
          • 整数是 int 型,占4个字节,有32位表示。其中最高位表示符号,0为正,1为负
          • 整数在内存中存储的是补码的二进制,正数的原码、反码、补码是相同的
          • 操作符对整数操作的流程:

          (1)先将整数的原码转换成反码

          (2)反码 +1转换成补码

          (3)最后对整数的补码进行操作

          (4)操作结束后,将操作后的补码 -1 转换成反码

          (5)将反码转换成最终的原码

          • 函数printf打印的是整数的原码

          3.1.1 正数左移1位

          代码如下(示例):

          int main()
          {
          	int a = 5;
          	int b = a << 1;//操作的补码二进制位,a本身结果不变
          	printf("%d\n", a);//打印5
          	printf("%d\n", b);// -10
          	return 0;
          }
          

          C语言操作符超详细讲解上篇

          结果运行见下图,与分析的结果一致,左移1位的效果相当于乘以2,左移在51单片机、STM32中,操作寄存器会经常用到。

          C语言操作符超详细讲解上篇

          3.1.2 负数左移1位

          int main()
          {
          	int a = -5;
          	int b = a << 1;//<< >> 操作的二进制位
          	printf("%d\n", a);//打印-5
          	printf("%d\n", b);// -10
          	return 0;
          }
          

          C语言操作符超详细讲解上篇

          运行结果见下图,和分析的结果一致

          C语言操作符超详细讲解上篇

          3.2 右移操作符

          右移移位规则运算分两种:

          • 逻辑移位:左边用0填充,右边丢弃
          • 算术移位:左边用原该值的符号位填充,右边丢弃

          3.2.1 正数右移1位

          int main()
          {
          	int a = 5;
          	int b = a >> 1;//右移不一定是除2
          
          	printf("%d\n", a);//打印-5
          	printf("%d\n", b);// -3
          	return 0;
          }
          

          下面分析右移的过程:正数的原码、反码、补码一样

          00000000 00000000 00000000 00000101 //5的二进制补码
          //算术右移:左边用原该值的符号位1填充,右边丢弃1
          00000000 00000000 00000000 00000010 //右移后的补码
          //右移后的补码就是右移后的原码  2

          结果见下图:

          C语言操作符超详细讲解上篇

          3.2.2 负数右移1位

          int main()
          {
          	int a = -5;
          	int b = a >> 1;//右移不一定是除2
          
          	printf("%d\n", a);//打印-5
          	printf("%d\n", b);// -3
          	return 0;
          }
          

          下面分析右移的过程:

          10000000 00000000 00000000 00000101 //-5的二进制原码
          11111111 11111111 11111111 11111010 //反码
          11111111 11111111 11111111 11111011 //补码:反码+1
          //算术右移:左边用原该值的符号位1填充,右边丢弃1
          11111111 11111111 11111111 11111101 //右移后的补码
          11111111 11111111 11111111 11111100 //反码:补码-1
          10000000 00000000 00000000 00000011 //原码  -3

          结果见下图:

          C语言操作符超详细讲解上篇

          3.3 移位操作符说明

          注意事项:

          • 右移操作符采用逻辑移位还是算术移位,取决于电脑编译器,我的是算术移位,所以举例以算术移位分析的,逻辑移位分析流程一样
          • 对于移位运算符,不要移动负数位,这个是标准未定义的,例如:
          int num = 10;
          num>>-1;//10右移-1位,这是错误的表达
          

          4、位操作符

          位操作符有:

          & //按位与     相同为1, 相异为0
          | //按位或     有1为1, 全0为0
          ^ //按位异或    相同为0, 相异为1
          //注:他们的操作数必须是整数

          int main()
          {
          	int a = 3;
          	int b = -5;
          	int c = a & b;
          	int d = a | b;
          	int e = a ^ b;//异或
          	//对应的二进制位:相同位0,相异为1
          	printf("%d\n", c);// 打印3
          	printf("%d\n", d);// -5
          	printfan("%d\n", e);// -8	
          	return 0;
          }
          

          00000000 00000000 00000000 00000011   3的补码
          11111111 11111111 11111111 11111011   -5的补码
          //按位与:  相同为1, 相异为0
          00000000 00000000 00000000 00000011    3的补码,原码表示3
          //按位或:   有1为1, 全0为0
          11111111 11111111 11111111 11111011   -5的补码,原码表示-5
          //按位异或: 相同为0, 相异为1
          11111111 11111111 11111111 11111000  补码
          11111111 11111111 11111111 11110111  反码
          10000000 00000000 00000000 00001000  原码 -8

          输出结果见下图,与分析一致:

          C语言操作符超详细讲解上篇

          4.1 练习 1

          不能创建临时变量(第三个变量),实现两个数的交换

          int main()
          {
          	int a = 3;
          	int b = 5;
          
          	printf("a=%d b=%d\n", a, b);
          	//第一种,常用的方法,创建中间变量
          	int tmp = a;
          	a = b;
          	b = tmp;	
          	//第二种,不创建变量
          	a = a + b;
          	b = a - b;
          	a = a - b;
          	//第三种,不创建变量,很难想到
          	a = a ^ b;
          	b = a ^ b;
          	a = a ^ b;
          	printf("a=%d b=%d\n", a, b);
          	return 0;
          }
          

          4.2 练习 2

          求一个整数存储在内存中的二进制中1的个数

          //举例: 5   &1, 然后右移1位, 再&1
          //00000000 00000000 00000000 00000101
          //00000000 00000000 00000000 00000001

          int main()
          {
          	int num = 0;
          	scanf("%d", &num);
          	int i = 0;
          	int cnt = 0;
          	//位操作
          	for ( i = 0; i < 32; i++)
          	{//每次右移一位就 &1
          		if (1==((num>>i)&1))
          		{
          			cnt++;//所有位与1,相同为1,相异为0
          		}
          	}
          	printf("%d", cnt);
          	return 0;
          }
          

          总结

          本文对部分操作符进行了,介绍,也分析了操作符的具体实现过程,这里了解原理即可,具体运算交给计算机执行,没必要每个都自己画图分析,耗时,不细心可能还会出错,32位二进制建议大家划分成4个字节,8位一组,好看一些,这在STM32 单片机对寄存器操作时,经常这样划分,一目了然。

          下一篇点这里直达

          声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。