首页->正文

熟悉或/与/位移操作符

2011-06-04 -Web开发

近期在阅读fastcgi协议,查看到这里
typedef struct {
     unsigned char nameLengthB0; /* nameLengthB0 >> 7 == 0 */

     unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
     unsigned char valueLengthB2;
     unsigned char valueLengthB1;
     unsigned char valueLengthB0;
     unsigned char nameData[nameLength];
     unsigned char valueData[valueLength
     ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
} FCGI_NameValuePair14;

完全不知所云,所以这里补充下相关操作符知识
1 与(&)
例如数字5(0000 0101)和6(0000 0110)
0000 0101
0000 0110
&
-----------
0000 0100

即对应位上如果都是1则结果位就是1,否则为0
2 或(|)
0000 0101
0000 0110
|
-----------
0000 0111

即对应位上如果有一个或者两个都是1,则为1,否则为0
实在记不清的话可以这样,把&理解为&&运算符,1理解为true,0理解为false,0&&1为false(0)只有true&true才是true(1)。同样|也可以这么理解,false||true还是true(1),只有false||false才是false(0)。但是使用时千万不要混淆 & |与&& ||

3 位移(右位移>> 左位移<<)
相当于把原始数的位向左或右移动指定的位数
如:5<<2结果为20
0000 0101
<<2
------------
0001 0100

左移后右边用0补充
再看右移的12>>2结果为3
0000 1100
>>2
----------
0000 0011

同样右移后左边也是补0

最后再看下fastcgi中那些介绍
unsigned char nameLengthB0;
nameLengthB0 >> 7 == 0

127(0111 1111)右位移7为0000 0000即0
而128(1111 1111)右位移7为0000 0001即1
因此通过右移7位就可以判断此数值是否大于127(Lengths of 127 bytes and less can be encoded in one byte, while longer lengths are always encoded in four bytes)

而大于127字节,则要在4bytes中编码,即
B = ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0

再看对4bytes编码的要求:
The high-order bit of the first byte of a length indicates the length's encoding. A high-order zero implies a one-byte encoding, a one a four-byte encoding.
即B3中最高位的1代表长度为4bytes编码,所以解码时需舍去B3中最高位的1,而0x7f为十六进制格式(二进制为0111 1111)。与操作(B3 & 0x7)后,则实现去1目的(无论0还是1,和0进行与结果都是0,而和1进行与操作则保留了B3剩余的位值)。接下来在进行左位移24(<< 24),即复原B3做为B的最高字节(1byte=8bits)。剩余的B2 B1 B0不涉及高位1去除,直接左位移16 8 0位即可(8*(n-1))

同理,根据值长度B,要编码为1byte或者4btyes的unsigned char 类型:
长度不大于127的可以直接1byte保存;
大于127的要编码为4bytes,首先对B中高位(左侧取前8位,也就是右移24位)的B3要做高位加1处理:
B3 = (B >> 24) | 0x80

0x80,二进制为1000 0000,进行或操作,根据或操作的定义和1进行或操作后都为1(0|1=1,1|1=1),而和0或操作则不影响原位值(1|0=1,0|0=0)

B2 = (B >> 16) & 0xFF

右位移16位后,和0xFF(二进制为1111 1111)进行与操作,为什么呢?想想,当右移16位后和八位全是1进行与操作会完全保留了这八位(0&1=0,1&1=1),而其余的位由于为0补齐(1&0=0,0&0=0),相当于去掉了B中前8位(32-8*3)
同理剩余的
B1 = (B >> 8) & 0xFF
B0 = B & 0xFF

相当于去掉了B中前16 24位。
再举例说明下:
B = 29297890 = 0000 0001 1011 1111 0000 1100 1110 0010
B3:
B>>24 = 0000 0001
 0000 0001
|1000 0000
-------------
 1000 0001

B2:
B >> 16 = 0000 0001 1011 1111
 0000 0001 1011 1111
&0000 0000 1111 1111 
---------------------------
 0000 0000 1011 1111

B1:
B >> 8 = 0000 0001 1011 1111 0000 1100
 0000 0001 1011 1111 0000 1100
&0000 0000 0000 0000 1111 1111
----------------------------------------
 0000 0000 0000 0000 0000 1100

B0:
 0000 0001 1011 1111 0000 1100 1110 0010
&0000 0000 0000 0000 0000 0000 1111 1111
-------------------------------------------
 0000 0000 0000 0000 0000 0000 1110 0010


操作符更详细的介绍
http://blog.csdn.net/weilaixi/archive/2009/02/23/3927826.aspx
二进制补码
http://hi.baidu.com/%B2%A8%C2%DE%B2%A8%C2%DE/blog/item/930b4a3653fab5d4a3cc2b06.html

fastcgi协议英文版http://www.fastcgi.com/devkit/doc/fcgi-spec.html
中文版http://fuzhong1983.blog.163.com/blog/static/1684705201051002951763/

下一篇 Fastcgi协议定义解释与说明

上一篇 一则cookie引起的问题

文章分类

开发小提示

  • 1:Mongodb中通过db.yourCollectionName. dataSize()查看某个文档的大小
  • 2:linux下用reset命令恢复查看二进制文件导致的命令行乱码
  • 3:查看MySQL表的索引情况show index from tableName
  • 更多...

交流

  • wangnow(a)126.com