28-位运算

本文详细介绍了位运算符,包括按位与(&amp;)、按位或(|)、按位取反(~)、按位异或(^)以及左移(<<)和右移(>>),并展示了它们在编程中的应用场景。此外,还讨论了逻辑运算与按位运算的区别,并提供了输出二进制数的方法。同时,提到了结构体中的位段(SFR)如何用于组合和访问特定位字段。
摘要由CSDN通过智能技术生成

运算符

按位与&

  • 如果(x)i == 1 , (y)i ==1 , 那么(x&y)i = 1
  • 否则的话(x&y)i = 0
  • 按位与常用于两种应用:
    1让某一位或某些位为0 :x & 0xFE
    2取一个数中的一段: x & oxFF
    请添加图片描述

按位或|

  • 如果(x)i == 1 或 (y)i ==1 , 那么(x&y)i = 1
  • 否则的话(x&y)i == 0
  • 按位与常用于两种应用:
    1让某一位或某些位为1 :x | ox01
    2把两个数拼起来: ox00FF | 0xFF00

按位取反~

  • (~x)i = 1 - (x)i
  • 把1位变为0,0位变1
  • 想得到全部位为1的数:~0
  • 7的二进制是0111,x | 7使得低三位为1,而
  • x & ~7,就使得低三位为0

逻辑运算vs按位运算

  • 对于逻辑运算,它只看到两个值:0,1
  • 可以认为逻辑运算符相当于把所有非0值都变为1,然后按位运算
    5&4 -> 4 而 5&&4 -> 1&1 -> 1
    5|4 -> 5 而 5| |4 -> 1 | 1 -> 1
    ~4 -> 3 而 !~4 -> !1 -> 0

按位异或^

  • 如果(x)i == (y)i ,那么(x^y)i = 0
  • 否则的话,(x^y)i == 1
  • 如果两个位相等,那么结果为0;不相等,结果为1
  • 如果x和y相等,那么x^y的结果为0
  • 对一个变量用同一个值异或两次,等于什么也没做
    eg: x^y^y -> x

左移<<

  • i<<j
  • i中所有的位向左移动j个位置,而右边填入0
  • 所有小于int类型,位移以int的方式来做,结果是int
  • x<<=1 等价于 x*=2
  • x<<=n 等价于 x*=2^n

右移>>

  • i>>j
  • i中所有的位向右移动j个位置
  • 所有小于int类型,位移以int的方式来做,结果是int
  • 对于unsigned类型,左边填入0
  • 对于signed的类型,左边填入原来的最高位(保持符号不变)
  • x>>=1 等价于 x/=2
  • x>>=n 等价于 x/=2^n

输出一个数的二进制

#include <stdio.h>
int main(int argc, char const *argv[])
{
	int number;
	scanf("%d", &number);
	unsigned mask = 1u<<31;   //将1移到最高位
	for ( ; mask ; mask >>=1 ) {    //将1不断向右移
		printf( "%d" , number & mask?1:0); //将1与0输出
	}
	printf( "\n");
	
	return 0;
}

扩展(MUC的SFR)

请添加图片描述
SBS = 1u<<2 -> 100
PE = 1u<<3 -> 1000
U |= SUS|PE ->1100 让某些比特位1
U &~SBS ->1011 ,&后0可以清除位
U &~PE->10111 ,&后0可以清除位 让某些比特位为0

段位

  • 把一个int的若干位组合成一个结构
struct {
	unsigned int leading : 3 ;
	unsigned int FLAG1 : 1 ;
	unsigned int FLAG2 : 1 ;
	int trailing :11;
};
  • 可以直接用段位的成员名称来访问
  • 比位移,与,或还方便
  • 编译器会安排其中的位排列,不具有可移植性
  • 当需要的位超过一个int时会采用多个int
#include <stdio.h>
void prtBin(unsigned int number) ;
struct U0 {
	unsigned int leading : 3;
	unsigned int FLAG1:1;
	unsigned int FLAG2: 1;
	int trailing: 27;
};
int main(int argc, char const *argv[])
{
	struct u0 uu;
	uu.leading = 2;
	uu. FLAG1 = 0;
	uu. FLAG2 = 1;
	uu.trailing = 0;
	printf( "sizeof( uu)=%luln", sizeof(uu) ) ;
	prtBin(*(int*)&uu) ;
	return 0;
}
void prtBin(unsigned int number)
{
	unsigned mask = 1u<<31;
	for ( ; mask ; mask >>=1 ) {
		printf( "%d", number & mask?1:0);
	}
	printf( "\n");
}


请添加图片描述

#include <stdio.h>
void prtBin(unsigned int number) ;
struct U0 {
	unsigned int leading : 3;
	unsigned int FLAG1:1;
	unsigned int FLAG2: 1;
	int trailing: 32;  // 此时已经超过了一个int
};
int main(int argc, char const *argv[])
{
	struct u0 uu;
	uu.leading = 2;
	uu. FLAG1 = 0;
	uu. FLAG2 = 1;
	uu.trailing = 0;
	printf( "sizeof( uu)=%luln", sizeof(uu) ) ;
	prtBin(*(int*)&uu) ;
	return 0;
}
void prtBin(unsigned int number)
{
	unsigned mask = 1u<<31;
	for ( ; mask ; mask >>=1 ) {
		printf( "%d", number & mask?1:0);
	}
	printf( "\n");
}

请添加图片描述
可以从输出结果看,用两个int 来表达变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值