Skip to content

位运算

964字约3分钟

2024-07-07

89.按位与按位或运算符

&(按位与):参加运算的两个数据,如果相应的二进制都为1,则该结果为1,否则为0

|(按位或):参加运算的两个数据,如果相应的二进制都为0,则该位结果都为0,否则为1

90.按位异或

相关信息

按位异或也称为XOF运算符,如果相应的二进制位不同,则该位结果为1,否则为0

#include <stdio.h>
void jh(void)                //交换两个变量的值,不使用中间变量
{
	int a = 3,b = 10;
	a = a^b;
	b = a^b;
	a = a^b;
	b = a^b;
	printf("%d,%d\n",a,b);
}
int main(void)
{
	int a = 123;
	printf("%d\n%d\n%d\n",a<<38,a<<(38%32),123<<38);   //让一个数值或者变量左移大于自身长度的位数或者使用左移右移的位数为负值,在不同的编译器中可能结果不一样,应尽量避免这种情况的发生
	return 0;
}

91.按位运算的综合运用

#include <stdio.h>
#include <stdlib.h>
int add(int a,int b)                               //整数相加返回其和
{
	int c;
	while(c = a&b);
	{
		a = (c^a) | (c^b);
		b = c<<1;
	}
	return a|b;
}     
int pv(int a,int index)                             //返回a的第index个二进制位的值
{
	if(index <= 0 || index >32)
	{
		printf("pv的参数有误,程序退出\n");
		exit(-1);
	}
	return 1&(a>>index-1);
}
int po(int a,int index)                                 //返回把a的第index个二进制位打开之后的值
{
	if(index <= 0 || index >32)
	{
		printf("po的参数有误,程序退出\n");
		exit(-1);
	}
	return a|(1<<index-1);
}
int pc(int a,int index)                               //返回把a的第index个二进制位关闭之后的值
{
	if(index <= 0 || index >32)
	{
		printf("pc的参数有误,程序退出\n");
		exit(-1);
	}
	return (~(1<<index-1)) &a;
}
unsigned pd(unsigned a,int start,int end)              //返回a的从第start到end个二进制位的值
{
	if(start > 0 && start <= end && end <=32)
		return a <<32-end >> 32-(end+1-start);
	printf("pd函数参数有误,程序退出\n");
	exit(-1);
}
unsigned pf(unsigned a,unsigned b,int start,int end)   //把b的低(end-1+start)个二进制位赋给 a当中的第start到第end个二进制位,最后返回a的值
{
	if(start > 0 && start <= end && end <=32)
	{
		int len = end+1-start;
		for(int i =1;i<len;++i)
		{
			if(pv(b,1))
				a = po(a,start++);
			else
				a = pc(a,start++);
		}
		return a;
	}
	printf("pf函数参数有误,程序退出\n");
	exit(-1);
}
int mul(int a,int b)                                   //返回两个整型相乘的积
{
	int s = 0;
	for(int i =1;i<=32;++i)
	{
		if(pv(b,i))
			s+=a<<i-1;
	}
	return s;
}
int chufa(int a,int b)                                 //返回两个整型的商
{
	if(b == 0)
	{
		printf("0不能被整除,程序退出\n");
		exit(-1);
	}
	if(a == 0)
		return 0;
	int a0 = pv(a,32);
	int b0 = pv(b,32);
	int zheng;
	if(a0^b0 == 0)
		zheng =1;
	else
		zheng =0;
	if(a0)
		a = ~(a-1);
	if(b0)
		b = ~(b-1);
	int i;
	for(i=31;i>-1;--i)
	{
		if(pv(a,i))
			break;
	}
	int shang = 0,bc = 1;
	while(i-- != 0)
	{
		if(b>bc)
		{
			shang <<1;
			if(i != 0)
				bc = bc<<1|pv(a,i);
		}
		else
		{
			shang <<=1;
			if(i != 0)
				bc = bc-b<<1|pv(a,i);
		}
	}
	return zheng?shang:~shang+1;
}
int main(void)
{
	printf("%d\n",add(23,14));
	printf("%d\n",pv(13,2));
	printf("%d\n",po(13,2));
	printf("%d\n",pc(13,3));
	printf("%u\n",pd(145,3,6));
	printf("%u\n",pf(15,4,2,3));
	printf("%d\n",chufa(13,2));
	return 0;
}

92.位段

提示

c允许一个结构体中以位为单位指定成员所占内存长度,这种以位为单位的成员称为“位段”,利用位段能够用较少的位数存储数据

举例

struct
{
	unsigned a:2;
	unsigned b:4;
	unsigned c:2;
	short m;
}data;              //a,b,c分别占2,4,2位,m为short型

注意

  • 给位段赋值注意位段的范围
  • 声明位段的一般形式:类型名 成员名:宽度 成员名可以省略代表无名位段
  • 一个位段必须存储到同一存储单元中,不能跨两个单元