千家信息网

C语言编程开发中位操作符有哪些

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容主要讲解"C语言编程开发中位操作符有哪些",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C语言编程开发中位操作符有哪些"吧!在C语言编程中,数据的位
千家信息网最后更新 2026年11月01日C语言编程开发中位操作符有哪些

本篇内容主要讲解"C语言编程开发中位操作符有哪些",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"C语言编程开发中位操作符有哪些"吧!

在C语言编程中,数据的位是可以操作的最小数据单位,理论上可以用"位运算"来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效率。

1. C语言中的位操作符

因为C语言的设计目的是取代汇编语言,所以它必须支持汇编语言所具有的运算能力,所以C语言支持全部的位操作符(Bitwise Operators)。位操作是对字节或字中的位(bit)进行测试、置位或移位处理,在对微处理器的编程中,特别适合对寄存器、I/O端口进行操作。因而本节将对此作比较详细地介绍。

6种位操作符的形式与含义如下:

& :按位"与"(AND);

| :按位"或"(OR);

^ :按位"异或"(XOR);

~ :"取反" (NOT);

》 :数据右移;

《 :数据左移;

1) 按位"与"运算

按位"与"运算符 & 的作用是对运算符两侧以二进制表达的操作数按位分别进行"与"运算,而这一运算是以数中相同的位(bit)为单位的。操作的规则是:仅当两个操作数都为1时,输出的结果才为1,否则为0。

例如:

a = 0x88,b = 0x81,则a & b 的运算结果如下:

0x88 1000 1000 a数

& 0x81 1000 0001 b数

= 1000 0000

其中,& 运算符让a数0x88与B数0x81的1位与1位、2位与2位……7位与7位分别相"与"。由于"与"运算的操作规则是,两个操作数中各位只要有1个为0,其结果中对应的位就为0。而a数与b数中只有***位(第7位)均为1,因而该位结果为1,其它各位结果都为0。

通常我们可把按位"与"操作 & 作为关闭某位(即将该位置0)的手段,例如我们想要关闭a数中的第3位,而又不影响其它位的现状,可以用一个数0xF7,即二进制数1111 0111去与a数作按位"与"运算:

0x88 1000 1000 a数

& 0xF7 1111 0111 屏蔽数

= 1000 0000

注意,这个数除第3位为0外,其它各位均为1,操作的结果只会将a数中的第3位置0,而a数的其它位不受影响。也就是说,若需要某个数的第n位关闭,只需要将该数与另一个数按位相与,另一个数除了相应的第n位为0外,其它各位都为1,以起到对其它各位的屏蔽作用。

上面的运算可以用a = a &(0xF7) 来表示,也可以用a & =(0xF7) 来表达。这两个表达式功能是相同的(见上节"复合赋值运算符"部分),但在源程序代码中常常见到的以第二种形式为多。

2) 按位"或"运算

按位"或" 运算符 | 的作用是对运算符两侧以二进制表达的操作数按位分别进行"或"运算,而这一运算是以数中相同的位(bit)为单位的。操作的规则是:仅当两个操作数都为0时,输出的结果才为0,否则为1。

例如:

a = 0x88,b = 0x81,则a | b 的运算结果如下:

0x88 1000 1000 a数

| 0x81 1000 0001 b数

= 1000 1001

通常我们可把按位"与"操作 & 作为置位(即将该位置1)的手段,例如我们想要将a数中的第0位和1位置1,而又不影响其它位的现状,可以用一个数0x03,即二进制数00000011去与a数作按位"或"运算:

0x88 1000 1000 a数

| 0x03 0000 0011 屏蔽数

= 1000 1011

注意,这个数除第0、1位为1外,其它各位均为0,操作的结果只会将a数中的第0、1位置0,而a数的其它位不受影响。也就是说,若需要某个数的第n位置1,只需要将该数与另一个数按位相"或",另一个数除了相应的第n位为1外,其它各位都为0,以起到对其它各位的屏蔽作用。上面的运算可以用a = a | (0xF7) 来表示,也可以用a | =(0xF7) 来表达。

3) 按位"异或"运算

按位"异或"运算符 ^ 的作用是对运算符两侧以二进制表达的操作数按位分别进行"异或"运算,而这一运算是以数中相同的位(bit)为单位的。异或运算操作的规则是:仅当两个操作数不同时,相应的输出结果才为1,否则为0。

例如:

a = 0x88,b = 0x81,则a ^ b 的运算结果如下:

0x88 1000 1000 a数

^ 0x81 1000 0001 屏蔽数

= 0000 1001

按位"异或"运算 ^ 具有一些特殊的应用,介绍如下:

① 按位"异或"运算可以使特定的位取反

例如:我们想让a数中的***位和***位取反,只要用0x81,即二进制数10000001去与它作按位"异或"运算,其运算结果同上式。经过操作后,***位的值已经由1变0,而***位的值也已经由0变1,起到了使这两位翻转的效果。其它位的状态保持不变。

可以看到,这个数除***位、***位为1外,其它各位均为0,操作的结果只会将a数中的第0、7位取反,而a数的其它位不受影响。也就是说,若需要某个数的第n位取反,只需要将该数与另一个数按位相"异或",另一个数除了相应的第n位为1外,其它各位都为0,以起到对其它各位的屏蔽作用。上面的运算可以用a = a ^ (0x81) 来表示,也可以用a ^ =(0x81) 来表达。

② 直接交换两个变量的值

例如,若有变量a = 3,b = 4,想要交换它们的值,可以做如下一组操作:

a ^ = b

b ^ = a

a ^ = b

首先,a ^ = b:

a 0000 0011

^ b 0000 0100

a = 0000 0111

其次,b ^ = a:

b 0000 0100

^ a 0000 0111

b = 0000 0011

***,a ^ = b:

a 0000 0111

^ b 0000 0011

a = 0000 0100

这样,a、b两个变量中的值就进行了对调。

4)"取反"运算

"取反"运算符 ~ 的作用是将各位数字取反:所有的0置为1,1置为0。例如:

1001 0110 取反后为0110 1001。

5) 数据右移

数据右移操作符 》 将变量的各位按要求向右移动若干位。右移语句的通常形式是:

variable 》右移位数

如:a = 1111 0000;进行 a = a 》 2 操作后,a = 0011 1100。

6) 数据左移

数据左移操作符 《 将变量的各位按要求向左移动若干位。左移语句的通常形式是:

variable 《 左移位数

如:a = 1111 0000;进行 a = a 《 2 操作后,a =1100 0000。

无论是左移还是右移,当某位从一端移出时,另一端出现的空白将以从外面移入的0(某些计算机是送1,详细内容请查阅相应C编译程序用户手册)来补充。这说明,移位不同于循环,从一端移出的位并不送回到另一端去,移去的位永远丢失了,同时在另一端只能补上相应位数的0。

移位操作可用于整数的快速乘除运算,左移一位等效于乘2,而右移一位等效于除以2。

如:x = 7, 二进制表达为:0000 0111,

x 《 1 0000 1110,相当于: x =2*7=14,

x 《 3 0111 0000,相当于: x=14*2*2*2=112

x 《 2 1100 0000, x= 192

在作第三次左移时,其中一位为1的位移到外面去了,而左边只能以0补齐,因而便不等于112*2*2=448,而是等于192了。当x按刚才的步骤反向移动回去时,就不能返回到原来的值了,因为左边丢掉的一个1,再也不能找回来了:

x 》 2 0011 0000, x=48

x 》 3 0000 0110 x=48/8=6

x 》 1 0000 0011 x=6/2=3

移位操作还可以配合其它位操作夫对寄存器或者数据I/O接口的各个位进行设置、检测,具体方法见下一节。

2.位操作符的一些实用方法介绍

1) 学会应用复合运算符

如前面所介绍的,位操作运算符可以和赋值运算符"="一起组成复合运算符。即如下5个:

《= 、》=、&=、^=、|=

其中,x 《 = y,相当于x = x 《 y;

x 》 = y,相当于x = x 》 y;

x & = y, 相当于x = x & y;

x ^ = y, 相当于x = x ^ y;

x | = y, 相当于x = x | y;

学会在C语言中使用复合运算符,可以简化源程序,优化目标程序。

2) C 语言中一些常见的位操作方法

由于我们此处学习C 语言的目的主要是为了开发微控制器的控制程序,为此我们特别关注一下对MPU的寄存器、I/O中某一位的操作语句。假如要对PORTA(端口A)的某些位进行赋值、置0、置1、取反、测试,可能会用到如一下一些语句:

① PORTA = 0x87

给整个PORTA赋值,作用是将1000 0111这个数赋予PORTA,即让PORTA的第0、1、2和7位置1,其它位清0。

② PORTA = (1《7)

给整个PORTA赋值,作用等价于PORTA = 0x80,将1000 0000这个数赋予PORTA,将指定的第7位置1,其余各位置0。只不过这里包括了两个步骤,即先是括号中的1《7操作,表示将0x01这个数左移7位,其值变成0x80,再将它赋予PORTA。

③ PORTA = (1《7) | (1《 3) | (1《 2)

给整个PORTA赋值,作用与②中的操作相同,但是是分别对7、3、2位置1,而将其它各位均置0。它先要分别对三个括号中给定的值进行移位操作,再将它们按位"与",***将值赋予PORTA。即:

1000 0000 (1《 7)

0000 1000 (1《 3)

| 0000 0100 (1《 2)

PORTA = 1000 1100

④ PORTA & = 0x80

使PORTA中的指定位清0,等价于PORTA =PORTA & (0x80)。由于0x80的二进制表达形式为1000 0000,利用其***位为1,其它各位均为0的特性,作为一个模板将其等于1的那些位(如本例中的第7位)屏蔽起来,使之保持不变,而将其它位清0(不管原来为0还是为1)。因为PORTA与0x80按位"与"的结果如下:

PORTA = 0x87 1000 0111

& 0x80 1000 0000

= 1000 0000

操作后,第7位的原来值1被保留,其它各个位被清0,其中***的3位原来为1,现在均为0了。

⑤ PORTA & = (1《7)

它也等价于PORTA & = 0x80:这里也包括了两个步骤,即先执行括号中的1《7操作,将0x01左移7位,其值变成0x80,再将它与PORTA做按位"与"。

该操作将除指定的第7位以外的各个位清0。

⑥PORTA & = ~ (1 《 7)

该指令在等号后面加了取反符号 ~ 。与上一条操作的区别是,在与PORTA做按位"与"前,还将0x80先行取反,将1000 0000转换成0111 1111,再做按位"与"操作。这样的操作结果是将指定的第7位清零,其它各位保持不变。

⑦ PORTA | = (1《7)

等价于PORTA = PORTA | (1《7),这里也是先执行括号中的1《7操作,将0x01左移7位,其值变成0x80,再将它与PORTA做按位"或"。

若操作前PORTA的初始值为0x07,则:

PORTA 0000 0111

| 0x80 1000 0000

PORTA = 1000 0111

该操作将***位置1,其它各位保持不变。

要注意的是,这条指令与PORTA = (1《7) 相比,虽然都可以使指定的某一位置1,但它们有着不同之处。PORTA = (1《7) 执行后,虽然某一位被置1了,但其它的位却被修改了,即不管PORTA的初始值为什么,原来为1的位都会被0覆盖,执行的结果总是为1000 0000。而本条指令却可以将其它位屏蔽起来,在改变要设置的那一位的同时,并不改变其它位的状态。

3) 巧用C语言中的位操作方法

① 将寄存器的指定位置1或清0

在实际应用中,经常利用 PORTA | = (1《 n) 这条指令将寄存器的任意位置1,而又不影响其它位的现有状态。比如说,你如果想将第4位置1,就使用 PORTA | = (1《 4) 就行了。当然,也可以使用 PORTA | = (1《 7) | (1《 4 ) | (1《 0) 这样的指令一次将设第8、5和1位置1,但又不影响到其它位的状态。

在实际应用中,经常利用 PORTA & = ~ (1《 n) 这条指令将寄存器的任意位清0,而又不影响其它位的现有状态。比如说,你如果想将第4位清0,就使用 PORTA & = ~ (1《 4) 就行了。

在启动nRF905芯片向空中发送数据时,采用以下函数:

void nrf905_TxSend(void)

{

PORTD|=(1《TRXCE);

DelayUs(1);//>10us

PORTD &= ~(1《TRXCE);

}

其中让PORTD中控制TRX_CE信号的那一位先置1,再清0,输出一高一低的脉冲信号,就在一个脉冲周期内,完成了一次数据发送。因为在程序的开头已经定义TRX_CE信号为PD6位,即TRXCE = 6,因而上面两行程序等价于:

PORTD|=(1《 6);

PORTD &= ~(1《 6);

② 测试寄存器指定位的状态

nRF905在接收数据过程中,要分别发出CD、AM和DR信号,而MPU也要分别对这些位进行检测,看它们是否变高,若变高,就执行下一步,否则就跳出分支,返回主程序。下面就是对这些位进行检测的一段函数:

void nrf905_RxRecv(void)

{

while ((PIND&(1《CD))==0); //CD引脚置1,检测到载波信号

while ((PIND&(1《AM))==0); //一般先AM=1指示地址匹配对

while ((PIND&(1《DR))==0); //DR=1时表示数据接收对而且Crc正确

//nrf905已经接收到数据

nrf905_ReadData(0);//读出nrf905中的数据

}

其中有:

while ((PIND&(1《DR))= =0); 或者:

if ((PIND&(1《DR))= =0); 语句,其功能就是对寄存器指定的位进行测试。

括号中是一个等式,我们将其拆分开介绍它的作用:

1《DR:

DR在程序的开始已经被定义为2,(1《DR)也就是(1《 2),表示将0x01左移2位,结果为0000 0100;

PIND& (1《DR):

PIND为PORTD端口的8位引脚的值,PIND& (1《DR)表示让它和(1《DR) 亦即和0000 0100按位相"与"。不管PIND的其它位为何值,由于和0相与,这些位的结果都为0,我们关心的只有第2位的状态。由于该位与1相与,只要DR为高,就会有:

PIND xxx x1xx

& 0000 0100

结果 = 0000 0100

结果的第二位的状态为1,也就是整个表达式 (PIND&(1《DR))= = 0不成立,语句的逻辑值为0。

若DR为低,则有:

PIND xxxx x0xx

& 0000 0100

结果 = 0000 0000

也就是整个表达式的结果为0,(PIND&(1《DR))= = 0成立,语句的逻辑值为1。根据括号中逻辑值的情况,while 或者if 语句再决定程序的流向。

到此,相信大家对"C语言编程开发中位操作符有哪些"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

运算 结果 位置 数据 运算符 语言 作用 操作符 两个 个数 二进制 寄存器 状态 程序 语句 影响 操作数 也就是 括号 指令 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 云南咖啡 与互联网科技公司 壹账通互联网科技 北京禾田雨橡互联网科技 唐信互联网科技 大连 广州紫鲸互联网科技 互联网公司会议桌创意科技软装饰 互联网金融科技公司干啥的 互联网时代科技改变生活 米聚互联网科技南京有限公司排面 深圳育鹏互联网科技有限公司招聘 2021互联网科技公司排名 上海钢联属于互联网科技股吗 广州千川互联网科技有限公司 产业互联网科技服务公司 东营紫格互联网科技 深圳互联网科技园地址 互联网金融金融科技 互联网科技大会大佬 长沙易易互联网科技有限公司 云之行互联网科技 互联网与科技发展 网络科技有限互联网 成都互联网科技公司100强 互联网科技创新服务 中科明德北京互联网科技 中国互联网有什么科技 宁波跨境商互联网科技有限公司 广东鹅鹅鹅互联网科技有限公司 数字互联网科技有限公司
0