移位和位操作符

前言

       在讲解移位操作符和位操作符之前,我们需要了解二进制的转换问题以及原码、反码和补码的问题,所以如果大家对这些有所了解,可以直接跳转到操作符那里查看学习。

进制转换

       在计算机里是使用二进制来存储数据的,所以我们需要了解一下二进制与十进制的转换问题。
       我们从十进制来着手出发,举个例子,152为什么是一百五十二,这时我们就要引入权重,152=1x10^2 + 5x10^1 +2x10^0 , 这是从10的0次方开始进行计算的,那么推演到二进制的话,就是从2的0次方开始,例如1010转换成十进制则表示多少呢?很简单,1010 = 0x2^0 + 1x2^1+ 0x2^2 +1x2^3 = 10

二进制和十进制的转换

       首先二进制转化十进制已经在上面提及过,就是每一位乘以相应的权重,然后依次相加就会得到十进制的表示。再举个例子吧,1100转换成十进制:
移位和位操作符_第1张图片
       十进制怎么转换成二进制呢,我们是这样处理的,一直除2,直到商为0,然后将余数从最后往前写就行了。
移位和位操作符_第2张图片
将余数从下往上写,就是1100

八进制、十六进制转换成十进制

       直接开门见山,十进制的每一位都是0~9这十个数字表示的,那么八进制的每一位是由0~7组成的,十六进制比较特殊,是由0 ~ 9和A ~ F(大小写均可)(A/a表示10,B/b表示11,C/c表示12…以此类推)表示的。根据上面提到的权重,以此类推,八进制就是8,十六进制就是16,直接上例子:
移位和位操作符_第3张图片

移位和位操作符_第4张图片

八进制、十六进制和二进制相互转换

       首先八进制和十六进制怎么转换成二进制的,我们可以先将他们转换成十进制,再转换成二进制,这样就可以了。
       那二进制怎么转化成八进制和十六进制的,我们看权重一个8可以由2的三次方组成的,一个16可以由2的四次方组成,这样借助这一个性质我们可以将二进制的每三位依次变为八进制位,将二进制的每四位依次变为十六进制位,大家可以看看下面的例子理解一下:
移位和位操作符_第5张图片

原码、反码、补码

       在计算机储存数据的时候,会有一个符号位(最开头的数位用1来表示负数,用0来表示正数)来表示正负,剩下的是数值位来表示数值。正数的原码、反码和补码是完全一样的,这里注意符号位是不会变的,负数的反码就是除了原码的符号位不变之外,其他位按位取反(就是0变成1,1变成0),补码就是在反码的基础上加1
这里我们以32位机器来举例:
移位和位操作符_第6张图片

移位操作符

       大家首先要记住计算机在内存中是以补码来储存数据的,也是用补码来进行运算的。

左移操作符 <<

       顾名思义就是补码向左移动对应的位数,右边补0:
       这里以左移移位举例:

1月24日

右移操作符 >>

       这里就有两种移位方式,一种是逻辑右移(就是补码向右移动对应的位数,左边补0),另一种是算术右移(保留符号位,补码向右移动对应的位数,左边补相应的符号位);具体执行哪一种是看编译器的,目前大多数编译器是算术右移。
我这里就举算术右移的例子:以右移一位举例:

1月24日 (1)

位操作符

一共有四种:&(按位与)        | (按位或)       ^ (按位异或)       ~(按位取反)
这些位操作符同样也是对二进制位来进行操作的,也是对补码进行操作的。

&

       只有都为1的时候才能为1,其他均为0.
移位和位操作符_第7张图片

|

       只有都为0的时候才能为0,其他均为1.
移位和位操作符_第8张图片

^

       相同为0,不同为1
移位和位操作符_第9张图片

~

       按位取反,1变为0,0变为1
移位和位操作符_第10张图片

实战

       给定两个不同的变量,在不创建第三个变量的情况下,怎么才能将这两个变量交换数值

#include 

int main()
{
	int a = 5, b = 10;
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("a=%d b=%d", a, b);
	return 0;
}

你可能感兴趣的:(初始c语言,c语言)