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

位操作的优势

[复制链接]
ctang 发布时间:2017-9-20 15:27
本帖最后由 ctang 于 2017-9-20 15:27 编辑
! S/ M) a* r' Z7 }/ D2 C+ D* x2 l2 d
7 A( t9 n. S$ s* F2 S% u位操作的优势& s9 y" o, N7 a& [2 K
$ f" r  t3 ^$ s; |/ g8 |+ C
在C语言中,可以单独操控变量中的位。读者可能好奇,竟然有人想这样做。有时必须单独操控位,而且非常有用。* \! q/ r8 R" @7 s! Y1 P3 Z) T) ?+ {
' T  ~5 h6 C3 r( ?  a/ F
例如,通常向硬件设备发送一两个字节来控制这些设备,其中每个位bit都有特定的含义。另外,与文件相关的操作系统信息经常被储存,通过使用特定位表明特定项。许多压缩和加密操作都是直接处理单独的位。
- q, c& N9 l# u9 v. I) a, A7 X; J- L! L; ~; \+ s
高级语言一般不会处理这级别的细节。C在提供高级语言便利的同时,还能在为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代码的首选语言。
" J; r9 b1 o3 {& i/ q- W# _3 @6 r0 }- q6 e, e3 I& E
位操作的基本运算
0 B+ `0 y9 N8 T, D7 k! _  S. u( ]. b2 {$ O5 `  Y! A
反码或按位取反:~
" L3 p6 l8 ~7 d$ K  o9 o/ O3 l3 ]
一元运算符~把1变为0,把0变为1.* x- g% X7 L, W, N! ]: D1 k3 w

$ `9 @+ Q8 s) X9 b~(10011010)=(01100101)
  S; c4 \9 ?1 n$ Z
6 p  S+ w) D0 T按位与:&
5 z. ?: v& z: ?; p) H
8 Q, ~0 V, l7 ]2 J' N, S" G3 S相应位都为1时,结果才为1.
; {5 s! i! ^3 `8 y6 N- Z8 d! q  |, ~- M4 `
(10010011)&(00111101)=(00010001)1 O( Q& f/ M$ K$ I: d/ \( ?$ t/ ^

+ R6 Q& K0 B% D  Y1 d5 m. J! N% w6 Z按位或:|
5 {  e9 O1 j' n6 d) C$ N, J' P/ A* Q9 P6 }5 _$ a
相应位只要有1,结果就为1./ e8 E' s  Z, O- |) K* I- i4 w4 J
1 H1 s' f6 f/ k2 i+ W4 @9 z1 H
(10010011)|(00111101)=(10111111)0 H, u/ @. r& u! q

' k# d% o4 K# ?  C按位异或:^   v8 \1 y5 p5 f: a+ D) q* Y0 M
8 l# b- T7 G8 m! {! l6 N! G9 [1 Y1 S
相应位不一样,结果就为1.6 p- A9 b! k. t  s+ i
8 F- t% U& ]8 L5 N0 X, O5 d% m
(10010011)^(00111101)=(10101110)
7 h( i8 y7 H" D( W" Y/ U) V: L( l8 ?: W9 W( [1 K+ T5 E: N, j5 U
位操作的高级运算 1 m' G6 ~+ c! j1 M! ~
2 {% r# H) ~& \8 v2 o
掩码
# A/ t% @5 S/ N
6 h% l3 M; t! h* I8 X4 I/ ~% |**按位与&**运算符常用于掩码(mask)。所谓掩码指的是一些设置为开(1)或关(0)的位组合。3 m$ B# z  ^- v. q8 A/ _( I) S

( |( b! C. _/ y% P  n假设定义符号常量MASK为2,那么2 E: E" N5 \; V0 A

: H* r; N0 _- k! M    flags = flags & MASK! C" b8 w% c8 _! j  X
  }3 F$ O, t4 n% l. n" V$ N' M
可以这样类比:把掩码中的0看作不透明,1看作透明。这样flag & MASK的结果只有MASK为1的位才可见。
0 h0 F# ~9 h! L% O
/ ~* w8 Y/ D. _0 e( ^' ]$ G![]()
! D% e* x9 I  y9 A/ k5 X/ k5 I
1 }/ r4 a" _' d7 U& a* O7 n' n# D. j
下面这条语句是按位与的一种常见用法:6 H6 s/ m, J# u. L3 u
- M0 ]6 D! `2 d& v3 w
    ch &= 0xff;# g" o) _$ ]: A# L* g

5 n: W2 @2 V/ t6 V1 y这个掩码保持ch中最后8位不变,其他位都设置为0.% A5 N& m; D/ H2 w% m
; F' l* Z* f3 e/ R2 @
打开位(设置位) : `# V+ J, T6 d: u
" n- x$ J1 ?) M% M; B" d  K
打开一个值中的特定位,其他位保持不变。# H7 }. o  V# W$ U5 X
, l8 k7 }0 W. J  E9 g
例如,一台PC通过向端口发送值来控制硬件。如为了打开内置扬声器,必须打开1号位,同时保持其他位不变。这种情况可以使用**按位或|*** Y  v& E( i  l7 y0 [
4 g3 F( n% g4 k8 B1 y' u
以上一节的flags和MASK(只有1号位位1)为例。下面的语句:5 T, l% @, I8 a8 {* v

, o2 U$ i5 }! T% H    flags = flags | MASK;
% [7 d% J) I9 K; c, Z
+ n- B9 @. d3 F4 d0 R  T4 z* w& q) h把flags的1号位设置为1,其他位保持不变。
2 ?" L4 B. R7 V! ]1 Q% o6 c: r) i
6 S) w0 Q' a+ K1 ^( B 关闭位(清空位)
* [5 M8 I" E4 @( @& r' l

: I4 I7 I1 V5 [! E同样,有时需要在不影响其他位的情况下关闭指定的位。
) M$ L. v! x$ U$ i
+ e' Q% L. Q# ^8 b假设要关闭flags中的1号位。同样,MASK只有1号位为1(即,打开)。可以这样做:6 z  ^& ^" a! R$ L; W9 x9 I

& O6 X- d8 i' S4 t! w    flags = flags & ~MASK;# L( R( t' ~! S
" [8 z5 w/ n! z. W& W8 O
又如:(00001111)& ~(10110110)=(00001001)
9 u5 M. ?# |; @0 U; S& g, E& W4 |3 T1 t' M- |* K
MASK中为1的位在结果中都被设置为0,flags中与MASK未0相应的位在结果中都未改变。可以使用下面的简化形式:
' h6 ?& _0 ~7 c/ p! H: {1 x$ H5 J2 U6 N2 y
    flags &= ~MASK3 R4 P* O$ ?& Z; [0 K4 M1 t

9 v" w- ^5 k# v$ Q切换位
  E6 |5 }" V& v* }9 }9 @+ r  T+ i! c  p1 ^
切换位指的是打开已关闭的位,或关闭已打开的位。可以使用**按位异或运算符^**  ]; R& V) b4 t' F3 E  m* V
6 D7 @6 R3 M8 O  \1 d$ @
假设b是一个位(1或0),如果b位1,则1^b为0;如果b为0,在1^b为1.另外,无论b为1还是0,0^b均为b。因此,如果使用^组合一个值和一个掩码,将切换该值与MASK为1的位相对应的位,该值与MASK为0的位相对应的位不变。# E4 q/ a  R8 o. r
" r. o* ^* f' t. q
要切换flags中的1号位,可以使用下面方法:
+ O8 L) O! C9 I  r. O% S' L  _6 t* C2 D+ V
    flags = flags ^ MASK;" v7 y+ I4 h# J
   
& `7 F) ~- T7 I0 N    flags ^= MASK;$ `, Y3 K& A6 {' d+ i. c
* |8 B, y) r: C3 v7 ?; `
又如:(00001111)^(10110110)=(10111001)/ l6 i5 |: ?" }% q
. {3 O' G4 f* g
与MASK为1的位相对应的位都被切换了,与MASK为0的位相对应的位保持不变。3 }2 i, l  |% h* ~8 C% W6 B$ T1 a! Z

" U& g/ u2 K1 s$ B) ]; @) H检查位的值
" U% n1 }4 |8 c! F/ J2 @& T2 A9 ~0 V1 \; b  `! B0 r
flags中的1号位是否变为1?可以这样做:
9 b. C" `5 m" b% m- r$ |( L; B" @
    if((flags & MASK) == MASK)2 U+ g" s/ B& ?$ X+ o
        puts("Wow!");
: f/ b1 z. b" e" {+ T1 U( \$ e* n; }) n  F
" @9 t( @, K* e3 y4 \+ j" Q
收藏 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- F# }4 P1 z! U: n* }
stm32结合位带操作更爽。而且是原子操作化的读-修改-写

6 n( v0 e" z- C% f9 d* n是的。用其他非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 手机版