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

位操作的优势

[复制链接]
ctang 发布时间:2017-9-20 15:27
本帖最后由 ctang 于 2017-9-20 15:27 编辑 . Q- F0 S) a' i# W$ F1 j) j. B7 J

  ^. s+ x8 e+ v位操作的优势
! c+ X* W# [" ~
% K$ R9 f/ D1 i2 q, N# t# @在C语言中,可以单独操控变量中的位。读者可能好奇,竟然有人想这样做。有时必须单独操控位,而且非常有用。
: c- W  N# R6 k' `" @# m( z. x) s! z
例如,通常向硬件设备发送一两个字节来控制这些设备,其中每个位bit都有特定的含义。另外,与文件相关的操作系统信息经常被储存,通过使用特定位表明特定项。许多压缩和加密操作都是直接处理单独的位。
4 x  n, Y0 L) s% G3 j2 e. l3 b: `. I! r  e! y' u5 h! C
高级语言一般不会处理这级别的细节。C在提供高级语言便利的同时,还能在为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代码的首选语言。; u! B6 q; [0 I8 V5 U, R9 W

$ w. c4 a4 Q  A5 U- `位操作的基本运算4 \5 E' Z7 u& {2 `# {, L
( a: ]0 o% m( v' S4 C# N0 Q5 w
反码或按位取反:~
! @, y$ L% A7 [
# t1 a# j& j$ M9 m一元运算符~把1变为0,把0变为1.7 p: G1 l% S2 U8 x, A+ W) d
! T. \+ w4 K7 }2 H- d8 I+ u) a
~(10011010)=(01100101)' f; G- M& F! Z
- H* i6 m' u" T- Z/ l0 z* H& m
按位与:&
7 k( M( G% A/ _. ^. r+ U5 `
8 i' a: @5 o( _相应位都为1时,结果才为1.
2 C" E/ L) r, Y1 k5 E+ Y1 J8 s$ m) L
(10010011)&(00111101)=(00010001)
( A3 C1 D4 z" t% h8 ?9 }- _2 K; f  C3 K! T
按位或:| ! H3 J3 `: d7 A8 v* ?  l9 J
! A! e+ [! D9 ?
相应位只要有1,结果就为1.& m+ J2 ^; {) y  N/ S: g
2 t/ z& j$ M& ^6 i4 q
(10010011)|(00111101)=(10111111)
& P( s. H2 u0 r7 y: G$ W* J, {( d+ x& m% q4 e, |
按位异或:^ , t& P+ I" k  v3 e+ _
. l1 ?; }7 Q" Q
相应位不一样,结果就为1./ I: [  r5 g1 W6 S8 Z$ m

8 ?) l+ c* C: K  I9 P# [% p5 B$ r(10010011)^(00111101)=(10101110)
. Z3 ?$ P- a- B$ F% _! \- e0 y2 P) t* x7 W8 R3 p
位操作的高级运算
7 t5 G* {+ i  o' \2 H& n; X9 Q
) a- |& a! l4 K- |6 {" X7 g掩码 " W- s# [! D  @1 R( N

' m3 Z% @/ S) `! E  {/ m8 W  C**按位与&**运算符常用于掩码(mask)。所谓掩码指的是一些设置为开(1)或关(0)的位组合。
" X9 s, M) V# l# E3 A2 B* C" _% F! ]" a! ^) W
假设定义符号常量MASK为2,那么
. u9 y$ R0 O: i: I2 N2 u* s
' {2 U% ]3 h( \# J, V1 o6 R% O    flags = flags & MASK9 V8 u2 {# a  u2 @& w

# `" c5 w3 G- G; s3 J7 q可以这样类比:把掩码中的0看作不透明,1看作透明。这样flag & MASK的结果只有MASK为1的位才可见。
: m8 x! m0 q/ S2 d
' ~8 R0 {4 \# B$ I& P% h![](): j; T' I/ |. b* T
# V6 p( [1 H# w( v+ o  f
/ t" Q; w* w0 |
下面这条语句是按位与的一种常见用法:% z( N9 S7 ~7 H; O, ^( T

* u! k1 n8 {- X% n$ `    ch &= 0xff;
4 o3 X" A( ~% n, k% c
) M- t) Q& R. H2 s& y. x* q这个掩码保持ch中最后8位不变,其他位都设置为0.
! J: L- X* s4 a. |1 g  S5 F
7 c* A' y0 I5 r- Z4 a) M# \打开位(设置位) 0 H  t# n* g: B
3 s& `' n8 `' ~
打开一个值中的特定位,其他位保持不变。2 p: W# L2 x$ T* w! Y8 P

: O+ A& i. E, L1 i/ `  p) f例如,一台PC通过向端口发送值来控制硬件。如为了打开内置扬声器,必须打开1号位,同时保持其他位不变。这种情况可以使用**按位或|**5 s& f9 }$ o5 P9 E! C

: y0 q* R" l5 P以上一节的flags和MASK(只有1号位位1)为例。下面的语句:
: b  S# I0 K1 K' {9 a, }8 n: P  T; i& r3 F1 ~: W
    flags = flags | MASK;+ q' \' S! o8 ]
+ r& x2 l( t1 T. O
把flags的1号位设置为1,其他位保持不变。+ Q; V! N% H, I. d+ R+ m( k
1 l" X6 U  v: Q$ p
关闭位(清空位) & ?# Q- N  ]1 d! U% i6 ^2 \

! m3 I' n* e% m$ E/ C0 l同样,有时需要在不影响其他位的情况下关闭指定的位。
6 u' j  y( s  t' v
2 E( x" K/ {/ O5 E/ G5 |) \! U假设要关闭flags中的1号位。同样,MASK只有1号位为1(即,打开)。可以这样做:
$ H6 F1 B9 i  [6 D, h$ m; T+ q! V+ o! O% D/ a. r
    flags = flags & ~MASK;
; I; {  X: O# L. X. x: R* L  z2 X- V
  _( m* Z' a( a. t又如:(00001111)& ~(10110110)=(00001001)
# ^7 j3 t% d0 m  B! [6 T' O1 Y9 [+ Q0 L/ |6 V# d& c
MASK中为1的位在结果中都被设置为0,flags中与MASK未0相应的位在结果中都未改变。可以使用下面的简化形式:4 ]  l% L+ J5 [+ `( G
0 G7 V9 u6 S, {: i% `* w
    flags &= ~MASK, ]/ @: a2 n5 V  }  W

$ I' @8 w6 H+ a+ Q( X0 u1 u切换位
3 V) W5 E% {$ D* c+ U
+ ~) A0 e+ V, H7 c0 `- I切换位指的是打开已关闭的位,或关闭已打开的位。可以使用**按位异或运算符^**
+ Y% P. D. r2 U" M5 |0 s: u# Y1 r  D8 e( y5 f3 V/ ?5 B7 [) ]
假设b是一个位(1或0),如果b位1,则1^b为0;如果b为0,在1^b为1.另外,无论b为1还是0,0^b均为b。因此,如果使用^组合一个值和一个掩码,将切换该值与MASK为1的位相对应的位,该值与MASK为0的位相对应的位不变。% Y7 S6 [( Z. @' C; K
9 _4 E* h& @# v# L( O
要切换flags中的1号位,可以使用下面方法:
9 }- l+ K* t; I6 P; j* B
6 a# z+ |9 {) T" @& U    flags = flags ^ MASK;1 \3 l6 `, ~7 Y
   
3 r# C& k9 c* W+ O; {% s( [    flags ^= MASK;
7 D- D9 [8 X3 m. D  s, r
1 Q4 b. a! w* ]: [2 i+ k3 @又如:(00001111)^(10110110)=(10111001)
# d# r* e4 o- U+ }' P5 `# m. [- u8 z7 A9 }! d/ Q% z
与MASK为1的位相对应的位都被切换了,与MASK为0的位相对应的位保持不变。% X2 s0 Y$ w$ j( x$ V3 e
2 U8 A3 v# s. ]" j6 W) n1 |5 X
检查位的值 $ M4 Y( e* q) w

- O- T! R6 v0 B& C- r' yflags中的1号位是否变为1?可以这样做:
% e8 z$ ?* S' H) F2 ?& e/ |) S; G& B) K# _7 D
    if((flags & MASK) == MASK)
$ P' h; k. N: W. g2 j3 j        puts("Wow!");
1 ]5 z/ ^, Y; e% y5 \! j/ M8 p1 k7 ?3 o3 m; n9 r" w

+ x+ i9 p( P/ _
收藏 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:39
; U$ U# r  p/ Vstm32结合位带操作更爽。而且是原子操作化的读-修改-写
0 Z0 D8 N2 ]- B
是的。用其他非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管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版