C语言基础知识整理24位运算

位运算

位运算是C语言的重要特色,是其他计算机高级语言所没有的。

位运算是指以二进制位为对象的运算。

指针运算和位运算往往是编写系统软件所需要的。在计算机用于检测和控制领域中也要用到位运算的指针。

位运算与位运算符

位运算符

运算符

含义

运算符

含义

&

按位与

~

按位取反

|

按位或

<<

左移

^

按位异或

>>

右移

//位运算符中除了“~”以外,均为二目(元)运算符。

//参加位运算的对象只能是整型或字符型的数据,不能为实型数据。

 

“按位与”运算 a&b

参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。即0&0=0,0&1=0,1&0=0,1&1=1。

若参与“&”运算的是负数,则以补码形式表示为二进制数,然后按位进行“与”运算。

特殊用途

  1. 清零:与0按位与
  2. 取一个数中某些指定位:如取低字节可以与八进制数377按位与
  3. 要想将哪一位保留下来,就与一个数进行&运算,此数在该位取1。

 

“按位或”运算 a |b

两个对应的二进制位中只要有一个为1,该位的结果值为1。

即0|0=0,0|1=1,1|0=1,1|1=1。

常用来对一个数据的某些位置1。

 

“异或”运算 a^b

异或运算符“^”也称XOR运算符。若参加运算的两个二进制位异号,则得到1(真),若同号,则结果为0(假)。即0^0=0,0^1=1,1^0=1,1^1=0。

异或意思是判断两个相应的位值是否为“异”。为“异”(值不同)就取真(1);否则为假(0)。

 

应用

  1. 使特定位翻转:与1进行异或,可达到翻转效果
  2. 与0相^,保留原值
  3. 交换两个值,不用临时变量a=a^b;b=a^b;a=a^b;

//执行前两个运算相当于b=(a^b)^b=a^(b^b)=a^0=a

//执行三个操作相当于a=(a^b)^(a^b^b)=a^a^b^b^b=0^b^0=b

“取反”运算 ~a

“~”是一个单目(元)运算符,用来对一个二进制数按位取反,即将0变1,将1变0。

如想使一个16位整数a的最低一位为0:a=a&~1

 

左移运算 a<

“<<”用来将一个数的各二进制位全部左移若干位。

如: a=a<<2;//将a的二进制数左移2位,右补0,高位左移后溢出,舍弃。

左移一位相当于该数乘以2。//当左移溢出被舍弃的高位不包含1时。

若a为一个字节(8位)

a的值

a的二进制形式

a<<1

a<<2

64

01000000

0

10000000

01

00000000

127

01111111

0

11111110

01

11111100

左移比乘法运算快得多,有些C编译程序自动将乘2的运算应左移一位来实现

 

右移运算 a>>x

 “>>”为右移运算,低位舍弃,无符号数左补0。

有符号数,正数补0,负数取决于计算机系统,补0的称为“逻辑右移”,即简单右移,不考虑数的符号问题,补1的称为“算术右移”(保持原有的符号)。

右移一位相当于除以2。

 

位运算赋值运算符 &=,|=,>>=,<<=,^=

位运算符与赋值运算符可以组成复合赋值运算符。

 

不同长度的数据进行位运算

若两个数据长度不同进行位运算时,系统会将二者按右端对齐。若短数为正数,则左侧补满0;若短数为负数,则左侧补满1;无符号数,左侧补满0。

 

位段(位域) 类型名 [成员名]:宽度

向一个字节中的一个或几个二进制位赋值和改变其值的方法

  1. 人为地将一个整型变量data分为几段。

屏蔽字:把某一小段以外地信息屏蔽起来,不受影响,只使该段改变为0

data=data&~(15<<4)|(n&15)<<4//将data从右侧起第4到7位置为n

  1. 使用位段

C允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或“位域”(bit field)。利用位段能够用较少的位数存储数据。

//位段的空间分配方向因机器而异。一般是由右到左进行分配的。不必过问细节

可以直接对位段进行操作。例如赋值,但是赋值要注意位段允许的最大值范围。

关于位段的定义与引用:

  1. 声明格式:类型名 [成员名]:宽度

位段成员的类型可以指定为unsigned int或int型。“宽度”应是一个整型常量表达式,其值应是非负的,且必须小于或等于指令类型的位长。

  1. 对位段组,即使实际长度只占一个字节,但也分配四个字节。如果想指定某一位段从下一个存储单元(字)存放,可以用以下形式定义:

unsigned a:3;      (一个存储单元)

unsigned0          (表示本存储单元不再存放数据)

unsigned b:3;      (另一存储单元)

//本来ab应连续存放在一个存储单元(字)中,由于用了长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放。//存储单元可能一个或两个字节,看编译系统

  1. 一个位段必须存储在同一存储单元中,不能跨两个存储单元。如果第1个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段。
  2. 可以定义无名位段。

如:

unsigned  a     :1;

unsigned          :2;(无名字段,这两位空间不用)

unsigned  b     :3;

unsigned  c     :4;

  1. 位段的长度不能大于存储单元的长度,也不能定义位段数组。
  2. 位段中的数可以用整型格式符%d、%u、%o、%x输出:printf(“%d”,data.a);
  3. 位段可以在数值表达式中引用,它会被系统自动地转换成整型数。

如:data.a+5/data.b//合法

 

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部