操作符详解

C语言非常灵活,因为C语言有丰富的操作符,甚至可以直接操作到二进制的位。
挑战:要把C语言的这些操作符灵活的使用,也是需要深刻理解和长期使用的。
1.二进制
我们经常听到2进制,8进制、10进制、16进制这样的讲法,那是什么意思呢?其实2进制、8进制、10进制、16进制是数值的不同表示形式而已。
比如:数值15的各种进制的表示形式:

1  15的2进制:1111
2  15的8进制:17
3  15的10进制:15
4 15的16进制:F

首先我们先重点介绍一下二进制:
我们先从10进制讲起,其实10进制就是我们平常经常使用的,我们已经形成了很多尝试:
· 10进制中满10进1
·10进制的数字每一位都是0~9的数字组成
其中二进制也是一样的
·2进制中满2进1
·2进制的数字每一位都是0~1的数字组成
那么1101就是二进制的数字了。
1.1 2进制转10进制
其实10进制的123表示的值是一百二十三,那么为什么是这个值呢?其实十进制的每一位是权重的,10进制的数字从右向左是个位、十位、百位…,分别每一位的权重是10^0, 10^1, 10^2…
如下图:
在这里插入图片描述
2进制和10进制是类似的,只不过2进制的每一位的权重,从右向左是:2^0, 2^1, 2^2…
如果是2进制的1101,该怎么理解呢?
在这里插入图片描述
1.1.1 10进制转2进制数字
10进制的125转换的2进制:1111101

1.2 2进制转8进制和16进制
1.2.1 2进制转8进制
8进制的数字每一位是0~7, 0~7的数字,各自写成2进制,最多有3个2进制位就足够了,比如7的二进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算一个8进制位,剩余不够3个2进制位的直接换算。
如:2进制的01101011,换成八进制:0153,0开好头的数组,会被当做8进制。
在这里插入图片描述

0:000  1:001   2:010   3:011   4:100  5:101  6:110  7:111

1.2.2 2进制转16进制
16进制的数字每一位是0~9, a~f的 ,0~9, a~f的数字,各自写成2进制,最多有4个2进制位就足够了,比如f的二进制1111,所以在2进制序列中最右低位开始向左每4个2进制位会换算一个16进制位,剩余不够4个二进制位的直接换算。
如: 2进制的01101011,换成16进制:0x6b,16进制表示的时候前面加0x
1个16进制位,描述清楚需4个2进制位。
在这里插入图片描述
2. 原码、反码、补码(这里不涉及小数即浮点数)
整数的2进制表示方法有三种,即原码、反码和补码
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位最高位的一位是被当作符号位,剩余的都是数值位。
正整数的原、反、补码相同。
负整数的三种表示方法各不相同。

原码: 直接将数值按照正负数的形式翻译成二进制得到的就是原码。
反码 :将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码+1就得到补码。
在这里插入图片描述

对于整型来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀
处理;
同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是
相同的,不需要额外的硬件电路。

3.移位操作符
· <<左操作符
· >>右操作符
注: 移位操作符的操作数只能是整数。
3.1 左操作符
移位规则:左边抛弃、右边补0
在这里插入图片描述
3.2右移操作符
移位规则:首先右移运算分两种:

  1. 逻辑右移:左边⽤0填充,右边丢弃
  2. 算术右移:左边⽤原该值的符号位填充,右边丢弃
    在这里插入图片描述
    在这里插入图片描述
    注:对于移位运算符,不要移动负数位,这个是标准未定义的。
    例如:
1. int num = 10 ;
2. num>>-1 ;//error 

4.位操作符:&、|、^
位操作符有:

1. & //按位与
2. | //按位或
3. ^ //按位异或
注:他们的操作数必须是整数。
#include<stdio.h>
int main()
{
	int a = 5;
	int b = -6;
	int c = a & b;//按位异或 - 对应的二进制位上相同则为0,相异则为1
	//00000000000000000000000000000101  -a
	//10000000000000000000000000000110  -b
	//11111111111111111111111111111001  b反
	//11111111111111111111111111111010  b补
	// 
	//00000000000000000000000000000101  a补
	//11111111111111111111111111111010  b补
	//00000000000000000000000000000000  &
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述

#include<stdio.h>
int main()
{
	int a = 5;
	int b = -6;
	int c = a ^ b;//按位异或 - 对应的二进制位上相同则为0,相异则为1
	//00000000000000000000000000000101  -a
	//10000000000000000000000000000110  -b
	//11111111111111111111111111111001  b反
	//11111111111111111111111111111010  b补
	// 
	//00000000000000000000000000000101  a补
	//11111111111111111111111111111010  b补
	//11111111111111111111111111111111  a^b
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述
接下来我们看一道变态的面试题:
不能创建临时变量(第三个变量),实现两个数的交换。
我们先用创建临时变量的方法

#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	int tmp = 0;
	tmp = a;
	a = b;
	b = tmp;
	printf("a = %d b = %d", a, b);
	return 0;
}

在这里插入图片描述
第二个思路

#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	a = a + b;
	b = a - b;
	a = a - b;
	printf("a = %d b = %d", a, b);
	return 0;  //有缺陷,整型存储的数值是有限制的,如果a,b值太大就会溢出
}

在这里插入图片描述
第三种(异或)

#include<stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a = %d b = %d", a, b);
	return 0;
}

在这里插入图片描述
异或支持交换律
这种异或操作有局限性
1.只能用于整数交换
2.代码可读性差
3.代码执行的效率也是低于使用第三个变量的方法

练习:编写代码实现:求一个整数存储在内存中的二进制中1的个数。
方法一

#include<stdio.h>
int main()
{
	int a = 15;
	//00001111
	int count = 0;
	while (a)
	{
		if (a % 2 == 1)
		{
			count++;
		}
		a = a / 2;
	}
	printf("count=%d\n", count);
	return 0;
}

在这里插入图片描述
方法二

#include<stdio.h>
int main()
{
	int a = 0;
	scanf("%d", &a);
	int i = 0;
	int count = 0;
	for (i = 0; i < 32; i++)
	{
		if (((a >> i) & 1) == 1)
		{
			count++;
		}
	}
	printf("%d\n", count);
	return 0;
}

在这里插入图片描述
方法三

int main()
{
	int n = 0;
	scanf("%d", &n);
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;

	}
	printf("%d\n", count);
	return 0;
}

在这里插入图片描述

5.逗号表达式

1  exp1,exp2,exp3,expN

逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右一次执行。整个表达式的结果是最后一个表达式的结果。

1  int a = 1;
2  int b = 2;
3  int c = (a>b, a=b+10,a, b=a+1);//逗号表达式  最后结果是c=13.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值