位运算(包括OR,AND,XOR,NOR,NAND,XNOR,以及&0xFF等常见应用)

位运算(包括OR,AND,XOR,NOR,NAND,XNOR,以及&0xFF等常见应用)

位运算是C语言的重要特点,是其他计算机高级语言所没有的,位运算是以二进制为对象的运算,二进制表示法与计算机内存完全对应,每个单元(位)都可以设置成开(1)或关(0)。而且位运算比正常的运算符速度要快很多,因为位运算是一种底层的运算,但是理解起来会偏难一些。

其他补充:

1、位运算符中除~外,均为耳目运算符

2、运算只能是整型或者字符型的数据,不然会报错

常见的位运算符

符号描述运算规则
&0&0=0; 0&1=0; 1&0=0; 1&1=1 同1为1
|0|0=0; 0|1=1; 1|0=1; 1&1=1 同0为0
~取反~1=0; ~0=1 取反
^异或0^0=0; 0^1=1; 1^0=1; 1^1=0 不同为1,相同为0
<<左移各二进制全部左移若干位,高位丢弃,低位补0
>>右移各二进制全部右移若干位,低位丢弃。对正数左补0,负数左补1

1、按位与操作

例如: 7&5的结果为5,计算如:在这里插入图片描述

常见用途

清零: 如果想将一个单元清零,让其与一个各位都为0的数值相与

取数(常见保留低八位,或者低16位,图像中常见):

例如,X=1001110101, 进行操作 X&0xFF 之后得到 01110101 Y=10000000000100111,进行操作 Y&0xFFFF 之后得到 0000000000100111

2、按位或操作

例如: 7|5的结果为7,计算如:

常见用途

负数补码

将一个数的某些‘’位‘置为1 例如:把Z=10100110的低4位的数置为1,Z|00001111即可满足目的。

3、取反运算

例如:~7的结果为-8,计算如:

常见用途:

使一个数的最低位为0,例如:Q&~1, ~1的值为1111111111111110,在与操作之后,最低位一定为0,~的优先级高于算数运算符、关系运算符、逻辑运算符等

4、异或运算 不同为1,相同为0

例如:10^-9的结果为-3 计算如:在这里插入图片描述

即 0000 1010 ^ 1111 0111 = 1111 1101(补码) 原码即为1000 0011 即10^-9 = -3

常见用途:

使特定位翻转:例如Q=10110110,使Q低4位翻转,用X ^ 0000 1111 = 1011 1001即可得到

与0相异,保留原值: Q^0000 0000 = 10110110

交换A和B:

void swap(int &a, int &b)
{
    a = a^b;
    b = a^b;
    a = a^b;
}

不推荐以上这个交换方式,相应还有一种加减的方法交换数值(如下所示),同样不推荐,难懂且效率不如中间临时变量的方法。

void swap(int &a, int &b)
{
	a = a + b;
	b = a - b;
	a = a - b;
}

5、左移运算

将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)

例如:X =18; X= X <<2,结果为72 计算如:在这里插入图片描述

上述左移一位后X=X*2; 若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2

6、右移运算

将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃

例如:X =18; X= X >>2,结果为4 计算如:

常见用途:

操作数每右移一位,相当于该数除以2(向下取整)。

注意

移位运算符在C++中会生成一个新值,但不回修改原来的值,例如:

int x = 27int y = x << 2;
cout << y << endl;
y << 3;
cout << y << endl;

上述代码两次输出的值均为108,即不会修改x的值,表达式x<<2使用x的值来生成一个新的值,就像x+3会申城一个新值,但不会修改x一样,如果要用移位运算符来修改变量的值,则必须使用赋值运算符,可以使用常规的赋值运算符或者<=运算符,如:

x = x<<4;
y <<=2

位运算的一些其他应用:

1、判断奇偶数

对于除0之外的任何数,使用X&1==1作为逻辑判断即可,例如:

x = 21;
if(x&1==1)
{
    cout << "x为奇数";
}

2、判断某个二进制是否为1

//例如判断x的第五位是否为1,十六进制的0x10转换为二进制是0001 0000
if(x&0x10==1)
{
    cout << "x为奇数";
}

3、求平均数

int average(int a, int b)
{
	return (a & b) + ((a ^ b) >> 1);
    //也可以用:return a - ((a - b) >> 1);
    //上面第一个会向下取整,第二个向上取整,例如输入10,11时,第一个返回10,第二个返回11
}

4、判断两个数是否异号

bool jtn(int a, int b) 
{
	return ((a^b) < 0);
}

5、数据加密

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define KEY 0x75
int main()
{
	char p_data[16] = { "我和我的祖国" };
	char Encrypt[16] = { 0 }, Decrypt[16] = { 0 };
	for (int i = 0; i < strlen(p_data); i++)//加密
	{
		Encrypt[i] = p_data[i] ^ KEY;
	}

	for (int i = 0; i < strlen(Encrypt); i++)//解密
	{
		Decrypt[i] = Encrypt[i] ^ KEY;
	}

	printf("Initial date:  %s\n", p_data);
	printf("Encrypt date:  %s\n", Encrypt);
	printf("Decode date:  %s\n", Decrypt);
	return 0;
}

上述输出结果为:

Initial date: 我和我的祖国
Encrypt date: 户细户辣虖
Decode date: 我和我的祖国

6、取绝对值(效率高)

int abs(int n)
{
  return (n ^ (n >> 31)) - (n >> 31);
}

或者

int abs(int n)
{
  int i = n >> 31;
  return i == 0 ? n : (~n + 1);
}

其他操作参见https://zhuanlan.zhihu.com/p/148790042

另外对于一些符号,例如OR,AND,XOR,NOR,NAND,XNOR以及其实现等简单说一下

OR|
AND&
XOR异或^
NOR或非~(a|b)
NAND与非~(a&b)
XNOR异或非~(a^b)

对于以上提到的&0xFF可以参考 https://blog.csdn.net/i6223671/article/details/88924481

更多位运算(涉及原码补码等)参考 https://zhuanlan.zhihu.com/p/42175031

很多代码参考:https://zhuanlan.zhihu.com/p/148790042

https://blog.csdn.net/weixin_42216574/article/details/82885102

https://tangxuan1023.github.io/2018/02/09/%E4%BA%A4%E6%8D%A2%E4%B8%A4%E6%95%B0%E7%9A%84%E5%80%BC/#more

  • 17
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值