C位操作符

news2024/11/24 7:01:12

目录

一、位操作符

1.位与&

2.位或|

3.位取反~

4.位异或^

5.位与,位或,位异或的特点总结

6.左移位《《  右移位   》》

二、位与,位或,位异或在操作寄存器时的特殊作用

1.寄存器操作的要求(特定位改变而不影响其他位)

2.特定位清零用&

3.特定位置1用|

4.特定位取反用^

三、用位运算构建特定二进制数

1.寄存器位操作经常需要特定位给特定值

2.使用位移获取特定位为1的二进制数

3.再结合位取反获取特定位为0的二进制数

4.总结:

四、位运算实战

1.例题1

2.例题2

3.例题3

4.例题4

5.例题5

6.例题6

7.例题7

8.例题8

方法1:

方法2:

五、用宏定义完成位运算

1.直接用宏来置位【赋1】,复位【赋0】(最右边为第1位)

1.1

1.2

1.3

2.截取遍历的部分连续位


一、位操作符

1.位与&

(1)位与符号是一个&,两个&&是逻辑与

(2)真值表:1&0=0   1&1=1   0&0=0    0&1=0

(3)从真值表可以看出:位与操作的特点是,只有1和1位于结果为1,其余全是0

(4)位于和逻辑与的区别:位与时两个操作数是按照二进制位批次对应位相与的,

        逻辑与是两个操作数作为整体来相与的(举例:0xAA&0xF0=0xA0    ,0xAA && 0xF0=1)

2.位或|

(1)位或符号是一个|,两个||是逻辑或

(2)真值表;1|0=1 1|1=1 0|0=0 0|1=1

(3)从真值表可以看出:位或时两个操作数是按照二进制彼此对应位相与的,

                                         逻辑或是两个操作数作为整体来相或的。

3.位取反~

(1)C语言中位取反是~,C语言中的逻辑取反是!

(2)按位取反是将操作数的二进制位逐个按位取反(1变成0,0变成1)

        逻辑取反是真(在C语言中只要不是0的任何数都是真)变成假(在C语言中只有0表示假),假变成真。

#include<stdio.h>
int main() {
	int a = 45;
	int b, c;
	b = ~a;  //按位取反,逐个位操作,1变0,0变1
	c = !a;	//按逻辑取反【整体改变】,真变假,假变真
	printf("b=%d\n", b);//-64
	printf("c=%d\n", c);//0

}
#include<stdio.h>
int main() {
	

	int a = 45;
	int b, c;
	b = ~(~a);  //等价于~~a
	c = !(!a);	//等价于!!a
	printf("b=%d\n", b);//45
	printf("c=%d\n", c);//1

}

实验;

        任何非0的数被按逻辑取反再取反就会得到1

        任何非0的数被按位取反再取反就会得到它自己

4.位异或^

(1)异或真值表:1^1=0  0^0=0  1^0=1  0^1=1(记忆方法:2个数如果相等结果为0,不等结果为1

	//45:0010 1101
	//^
	//23:0001 0111
	//=   0011 1010=58
	unsigned int a = 45, b = 23;
	unsigned int c;
	c = a ^ b;//58
	printf("c=%d\n", c);

5.位与,位或,位异或的特点总结

位与:(任何数,其实就是1和0)与1位与无变化,与0位于变成0

位或:(任何数,其实就是1和0)与1位或变成1,与0位或无变化

位异或:(任何数,其实就是1和0)与1位异或会取反,与0位异或无变化

6.左移位《《  右移位   》》

C语言的位移要取决于数据类型

对于无符号数,左移动时右侧补0(相当于逻辑移位)

对于无符号数,右移动左侧补0(相当于逻辑移位)

对于有符号数。左移时候右侧补0(角算术移位,相当于逻辑移位)

对于有符号数,右移动时候左侧补符号位(如果整数就0,负数就补1,叫算术移位)

二、位与,位或,位异或在操作寄存器时的特殊作用

1.寄存器操作的要求(特定位改变而不影响其他位)

(1)ARM是内存与IO统一编址的,ARM中有很多内部外设,SoC中的CPU通过向这些内部外设的寄存器写入一些特定的值来操控逐个内部外设,进而操控硬件动作。所以可以说,读写寄存器就是操控硬件

(2)寄存器的特定是按位进行规划和使用。但是寄存器的读写却是整体32位一起进行的。(也就是说你只想修改

(3)寄存器操作要求是:在设定特定位时不能影响其他位。

(4)如何做到?答案是:读-改-写(三部曲)。读改写的操作理念,就是:当我想改变一个寄存器中某些特定位时,我不会直接去给他写,我会先读出寄存器整体原来的值,然后再逐个基础上修改我想要修改的特定位,再将修改后的值整体写入寄存器。这样达到的效果是:再不影响其他位原来值的情况下,我关心的位的值硬件被修改了。

2.特定位清零用&

位与:(任何数,其实就是1和0)与1位与无变化,与0位于变成0

(2)如果希望将一个寄存器的某些特定位变成0而不影响其他位,可以构造一个合适的1和0组成的数和这个寄存器原来的值进行位与操作,就可以将特定位清零

(3)假设原来32位寄存器中的值为:0xaaaa aaaa,我们希望将bit8-bit15清零而其他位不变,可以将这个数与0xffff 00ff进行位与即可【想要变成0的位直接写上0,其他位写1即可】

#include<stdio.h>
int main() {

	unsigned int a = 0xaaaaaaaa;
	unsigned int b = 0xffffffff;
	unsigned int c;
	//将想要变成0的位置写上0,其他位写上1
	c = a & b;
	printf("c=0x%x\n", c);//0xaaaaaaaa
}

3.特定位置1用|

位或:(任何数,其实就是1和0)与1位或变成1,与0位或无变化

(2)要置1的位写上1,其他位为0,然后将这个数与相关的数进行位或

	//位或:特定位置1用|
    //把寄存器值的bit4-bit7置1,其他位不变
	unsigned int a = 0x123d0c57;
	unsigned int b = 0xf0;
	unsigned int c;
	c = a | b;
	printf("c=0x%x\n", c);//0x123d0cf7

4.特定位取反用^

位异或:(任何数,其实就是1和0)与1位异或会取反,与0位异或无变化

(2)要取反的特定位为1,其他位取0,然后将这个数与原来的数进行位异或即可。

	//异或:特定位取反用^
    //把寄存器值的bit4-bit7取反,其他位不变
	unsigned int a = 0x123d0cd7;
	unsigned int b = 0xf0;
	unsigned int c;
	c = a ^ b;
	printf("c=0x%x\n", c);//0x123d0c27

三、用位运算构建特定二进制数

1.寄存器位操作经常需要特定位给特定值

(1)由上节课可以找到:对寄存器特定位进行置1或者清0或者取反,关键性的难点在于要事先构建一个特定的数,这个数和原来的值进行位与,位或,位异或等操作,既可达到我们对寄存器操作的要求。

(2)解法1:用工具,难度也不大,操作起来也不是太麻烦

        解法2:自己写代码用位操作符号(主要是移位和位取反)来构建这个特定的二进制数

2.使用位移获取特定位为1的二进制数

(1)最简单的是用移位来获取一个特定位为1的二进制数。比如我们需要一个bit3-bit7为1(隐含意思是其他位全部为0)的二进制数,可以

        1)先写出5位为1的数(0x1f==>bit0-bit4)

        2)然后将这个数左移3位(0x1f<<3==》bit3-bit7)

(2)更难一点的:获取bit3-bit7为1,同时bit23-bit25为1,其他位为0

        ((0x1f<<3) | (0x7<<23))

#include<stdio.h>
int main() {

	//下面表达式的含义:位或说明这个数字由2部分组成,第一部分中左移2位说明第一部分从bit3开始
	//第一部分数字位0x1f说明这部分有5位,所以第一部分其实是bit3到bit7
	//第二部分的解读方法同样的,可知第二部其实是bit23到bit25
	unsigned int a;
	a = ((0x1f << 3) | (0x7 << 23));
	printf("a=0x%x\n", a);//a=0x38000f8
	return 0;
}

3.再结合位取反获取特定位为0的二进制数

(1)现在我们要获取bit4-bit10为0,其余位全部为1的数。怎么做?

(2)利用上面讲的方法就可以:(0xf<<0) | (0x1fffff<<11)


	unsigned int a;
	a = ((0xf << 0) | (0x1fffff << 11));
	printf("a=0x%x\n", a);//a=0xfffff80f
	return 0;

(3)但是这些存在问题:连续为1的位数太多了,这个数字本身就很难构造,所以这种方法的优势损失了

(4)思路是:先试图构造出这个数的位相反数,再取反得到这个数。(比如本例中要构造的数bit4-bit10为0,其他位为1),那我们先构造出一个bit4-bit10为1,其他位为0的数,然后对这个数按位取反即可。

	//使用位移+取反
	unsigned int a;
	a = ~(0x7f<<4);
	printf("a=0x%x\n", a);//a=0xfffff80f
	return 0;

4.总结:

(1)如果你要的这个数比较少位为1,大部分位为0,则可以通过连续很多个1左移n位得到

(2)如果你想要的这个数是比较少位为0,大部分为1,则可以通过先根据其位反数,然后再位取反来得到

(3)如果你想要得到的数中连续1(连续0)的部分不止1个,那么可以通过多段分别构建,然后再彼此位与【|】即可。这个时候因为参与位或运算的各个数为1的位是不重复的,所以这时候的位或其实相当于几个数的叠加。

四、位运算实战

要置1用|,用清零用&,要取反用^,~和《《 》》用来构建特定二进制数。

1.例题1

给定一个整形数a,设置a的bit3,保证其他位不变。

a=a|(1<<3)   或者  a|=(1<<3)

2.例题2

给定一个整形数a,设置a的bit3-bit7,保证其他位不变。

a=a|(0x1f<<3)  或者 a|=0x1f

3.例题3

给定一个整形数a,清除a的bit15,保证其他位不变。

a=a& ~(0x1<<15)   或者 a&=~(0x1<<15) 

4.例题4

给定一个整形数a,清除a的bit15-bit23,保证其他位不变。

a=a&(~(0x1ff<<15))  或者 a&=(~(0x1ff<<15))

5.例题5

给定一个整形数a,取出a的bit3-bit8

思路:

        第一步:先讲这个数bit3-bit8不变,其他位全部清零--->a=a&(0x3f<<3)

       第二步:再讲其右移3位得到结果

//第一步:把bit3到bit8的位保持不变,其余位全部清零
a=a& (0x3f<<3)
//第二步:将其右移3位
a>>=3;

6.例题6

将一个寄存器的bit7-bit17中的值赋值937(其余位不受到影响)

关键点:不能影响其他位,并不知道原来bit7-bit17中装的值

思路

        第一步:先将bit7-bit18全部清零,当然不能影响其他位

        第二部:将bit7-bit17进行赋值【使用”|“因为我们要赋值】

//第一步:bit7-bit17全部清零
a&=~(0x7ff<<7);
//第二步:bit7-bit17赋值937
a|=(937<<7);

7.例题7

将一个寄存器的bit7-bit17中的值+17(其余位不受到影响)

关键点:不知道原来的值是多少,

       思路:

                第一步:先读出原来的bit7-bit17的值

                第二步:给这个值加17

                第三步:将bit7-bit17清零

                第四步:将第二步算出来的值写入bit7-bit17

    unsigned int a=0xc30288f8;
    //第一步:先读出原来的bit7-bit17的值
    unsigned int tmp;
    tmp=a&(0x3ff<<7);//使用【&】和全1将这10位数进行计算
    tmp=tmp>>7//将其移动到低位取出

    //第二步:给这个值加17
    tmp+=17;

    //第三步:将bit7-bit17清零
    a=a & ~(0x3f<<7);

    //第四步:将第二步算出来的值写入bit7-bit17
    a=a| (tmp<<7);

8.例题8

将一个寄存器的bit7-bit17中的值赋值937(其余位不受到影响),同时个bit21-bit25赋值17

方法1:

unsigned int a;
unsigned int tmp;
//第一步:先将bit7-bit17位全部置为0
a=a&~(0x7ff<<7);
//第二步:将这几位进行赋值
a=a|(937<<7);
//第三步:先取出bit21-bit25
tmp=a&(0x1f<<21);
tmp=tmp>>21;
//第四步:将17加上
tmp+=17;
//第五步:将bit21-bit25置为0
a=a&~(0x1f<<21);
//第六步;将tmp放回到bit21-bit25
a=a|(tmp<<21);

方法2:

unsigned int a=0x30288f8;
a&=~((0x3ff<<7) | (0x1f<<21));//bit7-bit17和bit21-bit25全部清零
a|=((937<<7) | (17<<21));//937和17全部赋值

五、用宏定义完成位运算

1.直接用宏来置位【赋1】,复位【赋0】(最右边为第1位)

1.1

用宏定义将32位数的第n位(右边其算,也就是bit0是第二位)置位【变成1】

//第一题:用宏定义将32位数的第n位(右边其算,也就是bit0是第二位)置位【变成1】
//1U:表示无符号1---》(x | (1U <<(n-1)))
#define SET_BIT_N(x,n) (x | (1<<(n-1)))//因为我们是从bit0开始算的
int main() {
	unsigned int a = 0;
	unsigned int b = 0;
	b=SET_BIT_N(a, 4);//对应bit3
	printf("0x%x", b);

}

1.2

第二题:用宏定义将32位数x的第n位(右边其算,也就是bit0是第1位)清零【变成0】

#include<stdio.h>


//第二题:用宏定义将32位数x的第n位(右边其算,也就是bit0是第1位)清零【变成0】
#define CLEAR_BIT_N(x,n) (x&~(1U<<(n-1)))
int main() {
	
	//第二题
	unsigned int a = 0xffff;
	unsigned int b = 0;
	b= CLEAR_BIT_N(a, 4);//对应bit3
	printf("0x%x", b);//0xfff7

}

1.3

用宏定义将32位数x的第n位到第m位(右边起算,也就是bit0是第1位)置位【变成1】

我们需要一个算式得出(m-n+1)个1
算法:第一步:先得到32位1----》~(0U)
        第二步:将第一步得到的数右移x位即可得到(m-n+1)个1-----》~(0U)>>(32-(m-n+1))
        第三步:将得出的结果移回去原来的位置

//第三题:用宏定义将32位数x的第n位到第m位(右边起算,也就是bit0是第1位)置位【变成1】
//我们需要一个算式得出(m-n+1)个1
//算法:第一步:先得到32位1----》~(0U)
//		第二步:将第一步得到的数右移x位即可得到(m-n+1)个1-----》~(0U)>>(32-(m-n+1))
//		第三步:将得出的结果移回去原来的位置
#define CLEAR_BIT_N_M (x,n,m) (x| (((~0U)>>(32-(m-n+1)))<<(n-1)

	//第三题
	unsigned int a = 0x0;
	unsigned int b = 0;
	b = CLEAR_BIT_N_M(a,5,8);//对应bit3
	printf("0x%x", b);//

2.截取遍历的部分连续位

#define GETBITS(x,n,m) ((x&~(~0U) << (m-n+1)) <<(n-1)) >> (n-1))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1071536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

社科院与杜兰大学能源管理硕士项目——惊喜会随时间慢慢酝酿而出

我们越来越难感受到惊喜&#xff0c;按部就班的生活让我们丧失了感知力&#xff0c;我们再难以被简单的确幸所打动。试试停下脚步&#xff0c;惊喜往往不期而遇。社科院与杜兰大学能源管理硕士项目是你人生中的小确幸吗 学习是一种持续不断的自我提升&#xff0c;它能让我们逐渐…

【Python_PySide2学习笔记(十五)】按键QPushButton类的基本用法

按键QPushButton类的基本用法 前言正文1、创建按键2、按键设置文本3、按键设置启用、禁用4、按键设置背景色及透明度5、按键设置字体、字体大小、字体颜色6、按键设置图标7、按键信号&#xff1a;被点击8、按键设置背景图片 前言 此篇文章中介绍PySide2中 按键QPushButton类的…

Cuckoo沙箱各Ubuntu版本安装及使用

1.沙箱简介 1.1 沙箱 沙箱是一个虚拟系统程序&#xff0c;允许你在沙箱环境中运行浏览器或其他程序&#xff0c;因此运行所产生的变化可以随后删除。它创造了一个类似沙盒的独立作业环境&#xff0c;在其内部运行的程序并不能对硬盘产生永久性的影响。 在网络安全中&#xff…

短视频时代的领军者:TikTok能否引领数字创新浪潮?

曾经&#xff0c;人们认为短视频只是娱乐和消遣的一种方式&#xff0c;然而&#xff0c;TikTok却颠覆了这一观念。它已经超越了娱乐&#xff0c;成为了一个强大的内容创作和传播平台&#xff0c;重新定义了数字时代的社交互动方式。 那么&#xff0c;TikTok是否真的能够引领创…

【arm实验1】GPIO实验-LED灯的流水亮灭

linuxlinux:~/study/01-asm$ cat asm-led.S .text .global _start _start: 1.设置GPIOE寄存器的时钟使能 RCC_MP_AHB4ENSETR[4]->1 0x50000a28 LDR R0,0X50000A28 LDR R1,[R0] 从r0为起始地址的4字节数据取出放在R1 ORR R1,R1,#(0x1<<4) 第4位设置为1 ORR R…

0基础学习VR全景平台篇 第105篇:调色原理和色彩分析

“我心藏瑰宝灿烂如歌&#xff0c;唯有画作可为我吟唱。” 绘画、摄影、音乐等一切艺术&#xff0c;皆如是&#xff0c;敬梵高。 本节教程邀请李小岩老师讲授&#xff0c;大家欢迎&#xff01; 大家好&#xff01;欢迎收看我们这一节的课程&#xff0c;我们这一节呢主要讲的是…

定时任务 - 若依cloud -【 132 ~ 133 】

132 定时任务相关使用 | RuoYi&#xff08;单独启动&#xff09; 1、后台添加定时任务处理类&#xff08;支持Bean调用、Class类调用&#xff09; &#xff08;1&#xff09;bean调用 bean调用&#xff1a;需要添加对应Bean注解Component或Service。调用方式&#xff1a;ryTa…

java实验(头歌)--java语言之继承多态

文章目录 第一题第二题第三题 第一题 package step1;import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.Scanner;public class ShapeTrouble …

flutter开发实战-inappwebview实现flutter与Javascript的交互JSBridge

flutter开发实战-inappwebview实现flutter与Javascript的交互JSBridge 在使用webview中&#xff0c;需要实现flutter与Javascript交互&#xff0c;在使用webview_flutter插件的时候&#xff0c;整理了一下webview与Javascript的交互JSBridge&#xff0c;具体可以查看 https:/…

设计模式_模板方法模式

模板方法模式 前言 行为型设计模式 关注对象和行为的分离。 关于父类与子类 调用时候 具体调用的哪一个&#xff1f; 普通方法调用编译时决定左边决定抽象/虚方法调用运行时决定右边决定 介绍 设计模式定义案例模板方法模式父类 定义了业务流程&#xff0c;其中一部分 延…

【韩顺平 零基础30天学会Java】面向对象编程(中级)

面向对象编程&#xff08;基础&#xff09;部分的习题还没看呢&#xff0c;先mark住&#xff01;&#xff01;&#xff01; IDE&#xff08;集成开发环境&#xff09;- IDEA IDE&#xff08;集成开发环境&#xff09;- Eclipse idea设置字体和颜色主题&#xff1a;菜单 file -…

linux相关指令

一、ls 指令 语法&#xff1a;ls [选项] [目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含文件。 -d…

【单调栈】下一个更大元素 III

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;下一个排列 写在最后 Tag 【单调栈】【数组】【字符串】 题目来源 556. 下一个更大元素 III 题目解读 找出大于整数的最小整数&#xff0c;这个最小整数必须由原来整数中出现的数字组成。 解题思路 方法一&#xff…

冲刺第十五届蓝桥杯P0003倍数问题

文章目录 原题连接解析代码 原题连接 倍数问题 解析 需要找出三个数字&#xff0c;三个数字之和是k的倍数&#xff0c;并且这个数字需要最大&#xff0c;很容易想到的就是将数组进行倒叙排序&#xff0c;然后三层for循环解决问题&#xff0c;但是这样会导致**时间复杂度很高…

Appium问题及解决:打开Appium可视化界面,点击搜索按钮,提示inspectormoved

打开Appium可视化界面&#xff0c;点击搜索按钮&#xff0c;提示inspectorMoved&#xff0c;那么如何解决这个问题呢&#xff1f; 搜索了之后发现&#xff0c;由于高版本Appium&#xff08;从1.22.0开始&#xff09;的服务和元素查看器分离&#xff0c;所以还需要下载Appium In…

深入了解“注意力”和“变形金刚”-第2部分

一、说明 在上一个故事中,我已经解释了什么是注意力机制,以及与转换器相关的一些重要关键字和块,例如自我注意、查询、键和值以及多头注意力。 在这一部分中,我将解释这些注意力块如何帮助创建转换器网络,并详细

sed 命令

sed是Stream Editor&#xff08;字符流编辑器&#xff09;的缩写&#xff0c;简称流编辑器。 sed 命令是一个面向行处理的工具&#xff0c;它以“行”为处理单位&#xff0c;针对每一行进行处理&#xff0c;处理后的结果会输出到标准输出stdout。sed 命令是很懂礼貌的一个命令&…

CentOS 7 使用Docker

参考资料 Docker命令大全 黑马程序员docker实操教程 &#xff08;黑马讲的真的不错 容器与虚拟机 安装 yum install -y docker Docker服务命令 启动服务 systemctl start docker停止服务 systemctl stop docker重启服务 systemctl restart docker查看docker服务状态 syste…

拨2个号时报错All TAP-Windows adapters on this system are currently in use.

管理员运行addtap.bat 可以看到&#xff0c;有两个TAP-Windows Adapter V9适配器了

拼多多API接口的使用方针如下:

了解拼多多API接口 拼多多API接口是拼多多网提供的一种应用程序接口&#xff0c;允许开发者通过程序访问拼多多网站的数据和功能。通过拼多多API接口&#xff0c;开发者可以开发各种应用程序&#xff0c;如店铺管理工具、数据分析工具、购物比价工具等。在本章中&#xff0c;我…