你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

位操作的优势

[复制链接]
ctang 发布时间:2017-9-20 15:27
本帖最后由 ctang 于 2017-9-20 15:27 编辑 / R, ^/ E! @$ A2 c- C
* C: [( I3 V7 M
位操作的优势& ?2 I; \5 `8 v: m  u) }1 T. S

3 O3 e. c, |8 n" Z0 k) ~3 u) e% h& U在C语言中,可以单独操控变量中的位。读者可能好奇,竟然有人想这样做。有时必须单独操控位,而且非常有用。' I2 H" E4 L: j
7 J  O- N$ H7 J! ]8 Z  p3 M
例如,通常向硬件设备发送一两个字节来控制这些设备,其中每个位bit都有特定的含义。另外,与文件相关的操作系统信息经常被储存,通过使用特定位表明特定项。许多压缩和加密操作都是直接处理单独的位。
, ^- G6 w0 J5 _* a" O2 T1 [
8 P4 q! J0 m; ?! k$ m8 C高级语言一般不会处理这级别的细节。C在提供高级语言便利的同时,还能在为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代码的首选语言。( U+ S, x9 P- v) X

& }4 P( m8 r2 E; e0 Q# ^位操作的基本运算
  Y+ P% a4 M4 Y2 K7 Y$ G) M1 A% a" Y/ E1 j2 x% E: n: b& v3 h" c
反码或按位取反:~ 3 P1 H8 o8 U/ O1 a/ H

$ ^/ \# F7 E; |1 f, g! [一元运算符~把1变为0,把0变为1.
/ L: E" e& Y, I; U0 H* U+ H5 X! L4 |* j& U
~(10011010)=(01100101)
2 D, `/ k5 V3 t
8 F) v# V- `% V按位与:&
- I- s" T% k4 n8 [6 K1 |9 o. w: w- ]+ G" W$ o
相应位都为1时,结果才为1.$ [6 Y4 T' R, ~0 ^, C% S
! J1 q/ |2 x; {$ h' z" j
(10010011)&(00111101)=(00010001)
! W& w. k0 g' W3 b. G
$ ^# p* w; d. N按位或:| , L! J' w6 |; [, l  Q5 N
4 C2 Z0 C% M! C( Q, W
相应位只要有1,结果就为1.# V. b/ I% r1 R3 G
6 P: @" \7 y; B8 Z7 [
(10010011)|(00111101)=(10111111)
5 \, |: `3 w" g- I
: u. s* K1 h" g& ?' y4 J, p0 |按位异或:^ 8 C1 S6 I$ ~, I: d! E

, Z0 e2 t' P2 v! D0 R/ `相应位不一样,结果就为1.  _! ^7 W) b) l2 W
. A" T( A4 z+ {+ V4 r1 b, U# p
(10010011)^(00111101)=(10101110)# c9 m6 G& K4 A- ~* a& C) R( k8 F
+ x/ `6 w0 p) B2 y, B5 h  g
位操作的高级运算
) l  d5 [9 S  u/ F6 t. H% g' M8 f0 w' M6 y" Q+ g* @
掩码 5 v( }, P0 D" |( ^& v
* h- W+ w& C8 i0 \" {/ H. p
**按位与&**运算符常用于掩码(mask)。所谓掩码指的是一些设置为开(1)或关(0)的位组合。
# ^" ?9 W& D; n9 g: {( K4 ?
5 h4 o8 f& s7 k! u1 i1 w假设定义符号常量MASK为2,那么$ A# I! S& d9 N

8 _  Q! |9 d4 O    flags = flags & MASK+ b* m' L  _5 P6 a& r

) L: Q2 f" I5 i3 J  A可以这样类比:把掩码中的0看作不透明,1看作透明。这样flag & MASK的结果只有MASK为1的位才可见。
) t/ m8 y; `5 |3 s- B5 V' e* d) ]
9 `4 z& ^0 v( t5 S. K! [![]()- i/ ?. L( Q5 E- G
- V- q, T2 J9 p* O

2 }4 J, p( j0 r/ t# I' O下面这条语句是按位与的一种常见用法:3 {$ l0 u8 Q  U3 _) a8 z" I# ]

9 |4 k5 F" d9 E* H3 G    ch &= 0xff;- J/ s! q8 F/ j4 |3 `
0 f/ o  \2 p  ~( |$ V6 X0 |( _% o
这个掩码保持ch中最后8位不变,其他位都设置为0.
4 [$ F1 z& _' D! t" Z% l: p. J" _$ X3 z/ B4 Z
打开位(设置位) " W- b, ?' d$ M7 t
: v( Z4 `- Z  |0 r
打开一个值中的特定位,其他位保持不变。
/ s2 K; I- q) R! X9 A( F. e5 J* W4 c8 j1 U
例如,一台PC通过向端口发送值来控制硬件。如为了打开内置扬声器,必须打开1号位,同时保持其他位不变。这种情况可以使用**按位或|**。' J( s6 V. {" p( T
( t$ v9 F0 I. d
以上一节的flags和MASK(只有1号位位1)为例。下面的语句:  y# l' y2 U: j( f* p( S: t
: D  G$ n2 @( |. i# Z: f- e' N% e
    flags = flags | MASK;9 E: r5 u2 n" A. E

6 |; T, n! ]9 k" B! |把flags的1号位设置为1,其他位保持不变。
+ T3 w3 x' F# o) J9 g2 ~# z. J' {1 S$ M
关闭位(清空位) ) m: r2 a$ j$ I9 U- i

5 y( u8 t# g  a0 I# d  ~& ]5 O  @同样,有时需要在不影响其他位的情况下关闭指定的位。8 r) n! g, p' Q* k; D' h7 d, Z
2 P( |; q5 a2 E; s6 S: N$ v/ ?
假设要关闭flags中的1号位。同样,MASK只有1号位为1(即,打开)。可以这样做:- h/ H: F, f6 e9 d
9 s' E( I: w& \2 [9 y1 a6 Z
    flags = flags & ~MASK;& m$ H( X. f8 i
# v% V% Z6 p+ Y8 N$ e6 S$ ]; N  s
又如:(00001111)& ~(10110110)=(00001001)
3 A1 {2 ~0 h  H& Z0 d' L. O+ K# ~6 _  ~
MASK中为1的位在结果中都被设置为0,flags中与MASK未0相应的位在结果中都未改变。可以使用下面的简化形式:$ r4 m  s! K0 Q1 O% `4 l% E9 H1 g

  v# k8 v. q3 ?2 l' |3 ]' H6 X    flags &= ~MASK4 V1 a0 o0 b# T
" U  x' h% P1 V9 M% M1 Q
切换位
& G7 z4 O; }1 `* \5 Q3 d5 ?: j1 j5 V# Z& C- F( m+ f3 c2 s
切换位指的是打开已关闭的位,或关闭已打开的位。可以使用**按位异或运算符^**。
4 d3 v# R  M- X0 ?- C- B0 ?, ^
' Y) V! q7 l- t8 ~' J假设b是一个位(1或0),如果b位1,则1^b为0;如果b为0,在1^b为1.另外,无论b为1还是0,0^b均为b。因此,如果使用^组合一个值和一个掩码,将切换该值与MASK为1的位相对应的位,该值与MASK为0的位相对应的位不变。
2 C+ y4 e; e7 W2 T7 x. g. }+ U$ B0 C1 r" x: g( U7 i/ v: F# R
要切换flags中的1号位,可以使用下面方法:
& `6 t% H9 D- H# ]8 g$ L
: B- q1 C5 L# \" e7 H    flags = flags ^ MASK;
$ p3 `! z# W, k% u8 H    7 z+ U' r8 K. n2 c- x
    flags ^= MASK;
8 V) c5 z0 l: G1 _+ [! y
& l0 j7 F- ^6 i  ~8 A9 b* s又如:(00001111)^(10110110)=(10111001)
* X6 P7 U. m- b: W
( Z) Z6 P1 w+ \与MASK为1的位相对应的位都被切换了,与MASK为0的位相对应的位保持不变。; R# R- G9 P4 B, C- T

9 C$ @3 @4 _1 K+ t检查位的值 9 s, r) Y' b6 I" U9 R5 l8 U9 l

$ g* i; o% P1 {. O1 E, j$ cflags中的1号位是否变为1?可以这样做:
( N1 ~* o! i5 s- A
6 E( ~" q  \( |3 D) \4 p    if((flags & MASK) == MASK)3 D2 j! c8 I6 W3 h- A
        puts("Wow!");
; w4 U) F7 ]( ^4 K: ?
/ `7 f1 S8 `6 {* ~6 k$ a3 |: w+ x: R; g+ j4 Y  u7 }' \& |1 i
赞 收藏 1 评论7 发布时间:2017-9-20 15:27

举报

7个回答
斜阳 回答时间:2017-9-20 15:39:58
stm32结合位带操作更爽。而且是原子操作化的读-修改-写
ctang 回答时间:2017-9-20 15:44:09
斜阳__ 发表于 2017-9-20 15:393 X9 B* P: Y. |$ {. w) R
stm32结合位带操作更爽。而且是原子操作化的读-修改-写
( q$ V) I5 ?( r; Z/ _
是的。用其他非C语言,感觉不到位操作的强大。
五哥1 回答时间:2017-9-21 00:56:46
这个位操作的用法很精妙,要多看多用,才能用好呀
子曰好人 回答时间:2017-9-21 10:23:33
位操作很奇妙,哈哈哈,用好了事半功倍啊
wofei1314 回答时间:2017-9-22 10:59:40
这个不错,很容易看懂
pythonworld 回答时间:2017-9-23 14:49:45
mark一下,有用!
张亚飞 回答时间:2017-9-23 15:57:04
异或操作相对用的少。可以当成一个技巧来用。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版