位操作简介, 介绍c/c++的位运算

位简介 

位,它是什么?你可能会问。 

简单来说,位就是1和0,在电脑中做的每一件事都是由它们组成的。电脑中所有的数据使用的是位。一个字节由8个位组成;一个字由两个字节组成,即16个位;而一个双字由四个字节组成,即32个位。 

0   1   0   0   0   1   1   1   1   0   0   0   0   1   1   1   0   1   1   1   0   1   0   0   0   1   1   1   1   0   0   0 
||..............|...............|...............|..............|| 
|+-   bit   31......|...............|...............|.......bit   0   -+| 
|...............|...............|...............|...............| 
+--   BYTE   3   -----+---   BYTE   2   ----+---   BYTE   1   ----+--   BYTE   0   -----+ 
|...............................|...............................| 
+-----------   WORD   1   ------------+-----------   WORD   0   ------------+ 
|...............................................................| 
+---------------------------   DWORD   -----------------------------+ 

使用字节,字或者双字来进行位操作显得比较美观,就像使用一个小型数组或结构。使用位运算,可以检查或设置单独某一位的值或组位的值。 

十六进制数和位的关系 

人们发现,使用二进制计数法表示数字比较的困难。为避免这一问题,采用十六进制计数法(基数为16)。十六进制的一位数字从0到15分别用二进制的四位来表示。四位一组,即半字节。一个字节有两个半字节,则可以用两位十六进制数表示一个字节的值。 

半字节   十六进制数 
======   ========= 
0000........0 
0001........1 
0010........2 
0011........3 
0100........4 
0101........5 
0110........6 
0111........7 
1000........8 
1001........9 
1010........A 
1011........B 
1100........C 
1101........D 
1110........E 
1111........F 

如果有一个字节,内容为字母‘r’(ASCII   码   114),则表示如下: 

0111   0010   二进制数 
7   2   十六进制数 

记为:0x72 

位运算符 

共有6种位运算符,如下: 

&   与运算符 
|   或运算符 
^   异或运算符 
~   取反运算符 
> >   右移运算符 
< <   左移运算符 

&   运算符 

&(与)运算要求有两个运算值,然后返回一个值,当且仅当两个运算值都位1时,返回值为1。如下表: 

1   &   1   ==   1 
1   &   0   ==   0 
0   &   1   ==   0 
0   &   0   ==   0 

一个字节可以包含位标志,而使用与运算可以通过设置掩码来检查某位的值。算法如下:它用来判断字节中的第四位是否为1 


BYTE   b   =   50; 
if   (   b   &   0x10   ) 
cout   < <   "Bit   four   is   set "   < <   endl; 
else 
cout   < <   "Bit   four   is   clear "   < <   endl; 

通过以下计算可以得到结果: 

....00110010   -   b 
&   00010000   -   &   0x10 
---------- 
....00010000   -   result 

所以,第四位为1。 

|   运算符 

|(或)运算符要求两个运算值,然后返回一个值,当且仅当两个运算值中有一个为1或都为1时,返回值为1。如下表: 

1   |   1   ==   1 
1   |   0   ==   1 
0   |   1   ==   1 
0   |   0   ==   0 

使用或运算可以保证字节中的某位为1。算法如下:它用来保证第二位总是为1 

BYTE   b   =   50; 
BYTE   c   =   b   |   0x04; 
cout   < <   "c   =   "   < <   c   < <   endl; 

通过以下计算可以得到结果: 

....00110010   -   b 
|   00000100   -   |   0x04 
---------- 
....00110110   -   result 

^   异或运算符 

^   (异或)运算符要求有两个运算值,然后返回一个值,当且仅当两个运算值中有一个为1但不同时为1时,返回值为1。如下表: 

1   ^   1   ==   0 
1   ^   0   ==   1 
0   ^   1   ==   1 
0   ^   0   ==   0 

使用异或运算可以翻转特定的位。即0变1,1变0。算法如下:翻转第三和第四位 

BYTE   b   =   50; 
cout   < <   "b   =   "   < <   b   < <   endl; 
b   =   b   ^   0x18; 
cout   < <   "b   =   "   < <   b   < <   endl; 
b   =   b   ^   0x18; 
cout   < <   "b   =   "   < <   b   < <   endl; 

通过以下计算可以得到结果: 

....00110010   -   b 
^   00011000   -   ^   0x18 
---------- 
....00101010   -   result 

00101010   -   b 
^   00011000   -   ^   0x18 
---------- 
....00110010   -   result 

~   取反运算符 

~(取反)运算符只要求一个运算值,然后将所有的1变成0,所有的0变成1。使用取反运算可以将某些字节置0,确保其它字节置1,而不用考虑 

数据的大小。算法如下:将所有位置1,而第一和第零位置0 

BYTE   b   =   ~0x03; 
cout   < <   "b   =   "   < <   b   < <   endl; 
WORD   w   =   ~0x03; 
cout   < <   "w   =   "   < <   w   < <   endl; 

通过以下计算可以得到结果: 

00000011   -   0x03 
11111100   -   ~0x03   b 

0000000000000011   -   0x03 
1111111111111100   -   ~0x03   w 

同&(与)运算符一起使用,可以使任意位置0。算法如下:将第四位置0 

BYTE   b   =   50; 
cout   < <   "b   =   "   < <   b   < <   endl; 
BYTE   c   =   b   &   ~0x10; 
cout   < <   "c   =   "   < <   c   < <   endl; 

通过以下计算可以得到结果: 

....00110010   -   b 
&   11101111   -   ~0x10 
---------- 
....00100010   -   result 

> > 和 < <   右移和左移运算符 

> > (右移)运算符和 < <(左移)运算符将数据右移或左移若干位。> > 右移运算从高位往低位移, < <左移运算从低位往高位移。 

BYTE   b   =   12; 
cout   < <   "b   =   "   < <   b   < <   endl; 
BYTE   c   =   b   < <   2; 
cout   < <   "c   =   "   < <   c   < <   endl; 
c   =   b   > >   2; 
cout   < <   "c   =   "   < <   c   < <   endl; 

通过以下计算可以得到结果: 

00001100   -   b 
00110000   -   b   < <   2 
00000011   -   b   > >   2 

位段 

位段是位运算中比较令人感兴趣的部分。使用位段可以在一个字节,字或双字内设置小型结构。例如:要记录日期,要求尽可能少的使用内存,则可以采用如下的结构申明: 

struct   date_struct   { 
BYTE   day   :   5,   //   1   to   31 
month   :   4,   //   1   to   12 
year   :   14;   //   0   to   9999 
}   date; 

在上面的例子中,日占据了最低的5位,月份占据了接下来的4位,年份为接下来的14位。则整个日期储存在三个字节的23位中。第二十四位被忽略。如果使用整形申明则将占据12个字节。 

|0   0   0   0   0   0   0   0|0   0   0   0   0   0   0   0|0   0   0   0   0   0   0   0| 
|                                                           |               |                   | 
    +------   year   ---------------+   month   +--   day   --+ 

如上所述,date类型使用的位段结构。这里使用的是BYTE。一BYTE为8位,使用的时候,编译器将申请一个BYTE来储存。如果结构超过8位,编译器将再申请一个BYTE,直到足够用来储存结构。如果使用字或双字,编译器将总共申请32位用来储存结构。 

怎样申明位段?首先申明位段变量,跟着冒号,然后是分配给变量的位数;每位段用逗号分隔,最后用分号表示申明结束。 

完成结构申明后,则可以通过存取标记方便的使用结构,同时也可以使用地址操作符使用结构的地址对结构进行操作。如下: 

date.day   =   12; 

dateptr   =   &date; 
dateptr-> year   =   1852;   

原文:http://topic.csdn.net/t/20031022/22/2384983.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值