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

位操作的优势

[复制链接]
ctang 发布时间:2017-9-20 15:27
本帖最后由 ctang 于 2017-9-20 15:27 编辑
% I& }! P, m/ w: I+ a% p
" M6 k% w! g) t5 L+ v位操作的优势
& R3 M3 `) T3 ~! O! M& t
2 i0 x! b+ ~6 m5 ^在C语言中,可以单独操控变量中的位。读者可能好奇,竟然有人想这样做。有时必须单独操控位,而且非常有用。: e1 e7 S) B) Y& S
9 m, B4 l  t( p
例如,通常向硬件设备发送一两个字节来控制这些设备,其中每个位bit都有特定的含义。另外,与文件相关的操作系统信息经常被储存,通过使用特定位表明特定项。许多压缩和加密操作都是直接处理单独的位。9 `, c2 p7 f! _1 A
$ {7 v0 ^. o6 X; R) d
高级语言一般不会处理这级别的细节。C在提供高级语言便利的同时,还能在为汇编语言所保留的级别上工作,这使其成为编写设备驱动程序和嵌入式代码的首选语言。
1 R+ {7 Y8 F, p+ |3 E+ z9 X* b( {6 a# E- r3 F# E
位操作的基本运算
% I, q% F" [6 `9 K3 A9 W9 `, Y( p. A
反码或按位取反:~ . ]" A! A' Q1 Y+ t% X$ t! W/ x

0 Q( O" v3 |2 r1 d; x一元运算符~把1变为0,把0变为1.' O5 S4 r( X: F' M+ o

+ {# T3 D; D% P1 u~(10011010)=(01100101)
+ W; S' ^/ Y) g; ?: y) k5 g2 R2 v
+ W& W5 R- T4 g3 w: T1 l按位与:& 9 I2 s' g% |8 `4 J, u3 D  R4 X
2 E, q- Q9 o, a; N
相应位都为1时,结果才为1.) O; l0 O6 Z3 E4 k# X0 H; I
6 \! V" q6 z; s, n( x$ z
(10010011)&(00111101)=(00010001)7 k1 F3 ^. H) T% Z' _
7 ^8 Z7 I- u" [
按位或:| 3 U) `3 a3 Z$ O

) q" q  @* Z8 n! L+ M6 |; V相应位只要有1,结果就为1.& W3 |; t% B4 f% C/ e

7 y/ K* Z% c1 G& B7 ~$ h+ l(10010011)|(00111101)=(10111111). E$ h. J) c/ z* E
; p1 b2 h9 \, A! x" k
按位异或:^ : g, W) s8 Q+ Z0 l4 i" `' o

5 z" O( \  ~) Q5 W5 E0 G相应位不一样,结果就为1.. |. L# ]+ S8 ^2 v( |" q
1 S0 g' X; {3 `( ]
(10010011)^(00111101)=(10101110)
2 ?; I- P# ]- h( q* t; H. H+ _* o4 b
: M2 m& B: U  c- J: _6 z& m6 J# [2 T位操作的高级运算
- g! E3 H* p! n( f( L) J+ D$ ?, h3 r1 H) U
掩码 $ D+ T6 r8 f$ U: Q
  n& I" c$ h. w! R
**按位与&**运算符常用于掩码(mask)。所谓掩码指的是一些设置为开(1)或关(0)的位组合。6 B+ K7 C; F- ]' X  N

* I! {! G' B: A5 W: ?) n9 X假设定义符号常量MASK为2,那么/ h, u$ r; d3 r) P6 Z! x
/ U$ r; l* l; w4 R; `- ?) k
    flags = flags & MASK5 p# d; y: `7 G5 q% z' F
9 D8 p) C( s% Z+ A: m
可以这样类比:把掩码中的0看作不透明,1看作透明。这样flag & MASK的结果只有MASK为1的位才可见。
0 S3 R- T, E4 j5 a2 Y1 c+ O# b" E) q2 P* y# G. p8 }7 I
![]()
# I4 a& }8 H# Q* `
. K5 U: w" u, j0 k# U) h" O  x) x6 y. k( W, E
下面这条语句是按位与的一种常见用法:
7 S7 h6 d! g) H+ Y9 X+ V: {2 ?4 ]' ^
    ch &= 0xff;
% e! F9 Q1 M! M9 U, A4 |8 Z$ I% ~9 K9 {6 d# g% Y
这个掩码保持ch中最后8位不变,其他位都设置为0.
& @7 n# I( P* r% a# @( y/ R
8 a& f( G  K; `$ m( H1 E打开位(设置位) 8 t  _1 x, @9 S' s& K. ?" d) f$ L

( G( l9 t0 p. W打开一个值中的特定位,其他位保持不变。, p0 l. F2 ^- C! q9 Y9 V

! w( o7 {* r: S' O  h3 y例如,一台PC通过向端口发送值来控制硬件。如为了打开内置扬声器,必须打开1号位,同时保持其他位不变。这种情况可以使用**按位或|**! v3 ]6 R, B: h/ E) V; K  t, ]4 B

7 r3 z6 s! [1 R/ V, {- A) W5 U0 v以上一节的flags和MASK(只有1号位位1)为例。下面的语句:" {6 b' d: ]( _- f! z/ v8 Y& C

, k# Z$ c! \& G    flags = flags | MASK;
7 p4 J) n* q5 E0 {+ j0 D# P8 J! ^  I+ Y: l2 o4 S0 s
把flags的1号位设置为1,其他位保持不变。# L* ~3 P0 K! O: P

0 b" ~. |7 m8 z# w. Q 关闭位(清空位)
- G4 J& o' F7 l- s  f( z/ P; O

+ G- b; {% i  j( {% {% F3 E3 ]同样,有时需要在不影响其他位的情况下关闭指定的位。
; h* W% h3 ?% I) B5 S' w( I9 [. k: I- n, T: X- |7 X
假设要关闭flags中的1号位。同样,MASK只有1号位为1(即,打开)。可以这样做:
; k) Q4 a* G4 O+ F2 Y" [3 w2 ^7 H
/ h7 `& F( h  @: Y    flags = flags & ~MASK;
1 `- f& m& @' A" @( Q4 K" v
- C8 z$ q0 f% G* s  S9 I又如:(00001111)& ~(10110110)=(00001001)
7 m, s% z0 v- S  `/ U, y/ ~8 j$ O$ _$ Q+ B. P1 X  s
MASK中为1的位在结果中都被设置为0,flags中与MASK未0相应的位在结果中都未改变。可以使用下面的简化形式:2 X0 h5 ^" @" L; _
' ^3 Z, T  ?; ^: Z0 z8 z7 H
    flags &= ~MASK
4 @+ ]. g- K/ U' U( y3 S! E: ]! a
切换位$ }1 k3 s: ]8 ^3 G& E! U

9 Q$ Z0 m! g5 H& h! A切换位指的是打开已关闭的位,或关闭已打开的位。可以使用**按位异或运算符^**& f$ f; W8 T6 D% ^
2 x; a( j6 d9 `$ s& ?; w
假设b是一个位(1或0),如果b位1,则1^b为0;如果b为0,在1^b为1.另外,无论b为1还是0,0^b均为b。因此,如果使用^组合一个值和一个掩码,将切换该值与MASK为1的位相对应的位,该值与MASK为0的位相对应的位不变。
, K' l; e3 {; l+ w2 d9 E, w% s2 ]9 Z5 M( A% a) j! Q
要切换flags中的1号位,可以使用下面方法:
6 {6 |/ t3 }& K6 H# `$ l5 W. x% `. S) k5 {; S; x7 I7 F# O
    flags = flags ^ MASK;6 O4 F- O' y+ M! y( O- z
    / h2 ^' v. X, F$ c* l/ E6 j$ \
    flags ^= MASK;; k1 _0 k7 j& q& y* ?; |; ?5 }

- \$ o- w( p* F4 i  W: Y又如:(00001111)^(10110110)=(10111001)* G! C! I  ?/ k+ w" }
) @. S; p5 F8 s% ?) v6 Q
与MASK为1的位相对应的位都被切换了,与MASK为0的位相对应的位保持不变。
# T3 b- d" P4 J& p1 G0 s$ l* H$ m" ~& q
检查位的值 / ^* o- o+ m4 z$ E/ m

. W" Q3 V6 h# C2 s: B! b9 g, lflags中的1号位是否变为1?可以这样做:( e1 m' m7 m  o) b% w
* `( r1 H% o0 S2 l6 O; c  p$ I
    if((flags & MASK) == MASK)9 x. ~8 z5 j. q; f
        puts("Wow!");9 G7 g8 W& |! e& k& U( e! @

& C4 q0 n( `. i2 N9 R
+ }. R6 O, C$ Y8 W
收藏 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% {5 R1 C  y7 G/ i) Y& P0 ystm32结合位带操作更爽。而且是原子操作化的读-修改-写
5 U  q3 p% U4 x; R* {5 P
是的。用其他非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 手机版