关于按位And和Shift操作的问题

时间:2010-07-14 06:40:58

标签: c++ bit-manipulation bitwise-operators

如果pData = "abc"

,以下行的具体用途如何?
pDes[1] = ( pData[0] & 0x1c ) >> 2;
pDes[0] = ( pData[0] << 6 ) | ( pData[1] & 0x3f );

4 个答案:

答案 0 :(得分:4)

好的,假设ASCII无法保证,pData[0]'a'0x61)而pData[1]'b'0x62 ):

pDes[1]:
    pData[0]               0110 0001
    &0x1c                  0001 1100
                           ---- ----
                           0000 0000
    >>2                    0000 0000  0x00

pDes[0]:
    pData[0]               0110 0001

    << 6           01 1000 0100 0000 (interim value *a)

    pData[1]               0110 0010
    &0x3f                  0011 1111
                   -- ---- ---- ----
                           0010 0010
    |(*a)          01 1000 0100 0000
                   -- ---- ---- ----
                   01 1000 0110 0010  0x1862

工作原理:

<< N只是意味着将位N位移到左侧,>> N是相同的但向右移位。

当且仅当两个输入中的相应位为1时,&and)操作才会将结果的每个位设置为1。

如果两个输入中的一个或多个相应位为1,则|or)运算将结果的每个位设置为1.

请注意,如果类型不够宽,0x1862将被截断以适合pDes[0]

以下C程序显示了这一点:

#include <stdio.h>

int main(void) {
    char *pData = "abc";
    int pDes[2];
    pDes[1] = ( pData[0] & 0x1c ) >> 2;
    pDes[0] = ( pData[0] << 6 ) | ( pData[1] & 0x3f );
    printf ("%08x %08x\n", pDes[0], pDes[1]);
    return 0;
}

输出:

00001862 00000000

并且,当您将pDes更改为char数组时,您会得到:

00000062 00000000

答案 1 :(得分:2)

&不合逻辑 - 它是按位的。

a为0x61,因此pData[0] & 0x1c给出

0x61 0110 0001  
0x1c 0001 1100
--------------
     0000 0000

>> 2将此位置向右移动两个位置 - 值不会因为所有位都为零而改变。

pData[0] << 6左移0x61 6位,以提供010000000x40

pData[1] & 0x3f

0x62 0110 0010
0x3f 0011 1111
--------------
0x22 0010 0010

因此它归结为0x40 | 0x22 - 再次|不符合逻辑,或者是符合逻辑的。

0x40 0100 0000
0x22 0010 0010
--------------
0x62 0110 0010

如果pDes不是char数组,结果会有所不同。左移0x61会给你0001 1000 0100 00000x1840 - (如果pDes是一个字符数组,左边的部分不在图片中)。

0x1840 0001 1000 0100 0000
0x0022 0000 0000 0010 0010
--------------------------
0x1862 0001 1000 0110 0010

pDes[0]最终会以0x1862或小数6242结束。

答案 2 :(得分:1)

C ++会根据字符编码将字符视为数字。因此,假设ASCII,'a'为97(其位模式为0110_0001),'b'为98(位模式0110_0010)。

一旦将它们视为数字,对字符的位操作应该更清晰一些。

答案 3 :(得分:0)

在C中,所有字符也是整数。这意味着"abc"相当于(char[]){0x61, 0x62, 0x63, 0}

& 逻辑AND运算符(&&)。它是bitwise AND,它在位级计算AND,例如

      'k' = 0x6b ->    0 1 1 0  1 0 1 1
            0x1c ->    0 0 0 1  1 1 0 0   (&
                    ———————————————————
               8 <-    0 0 0 0  1 0 0 0

这里& 0x1c的主要目的是从pData[0]中提取#2~#4位。 >> 2之后删除了额外的零。

同样,& 0x3f是从pData[1]中提取#0~#5位。

<< 6在位的最低端推送6个零。假设pDes[0]也是char,则最高6位将被丢弃:

     'k' = 0x6b ->                      0 1 1 0 1 0 1 1
                    << 6 = 0 1 1 0 1 0  1 1 0 0 0 0 0 0
                           xxxxxxxxxxx—————————————————
           0xc0 <-                      1 1 0 0 0 0 0 0

就位而言,如果

                 pData[1]                    pData[0]

pData -> b7 b6 b5 b4 b3 b2 b1 b0     a7 a6 a5 a4 a3 a2 a1 a0

然后

pDes  ->  0  0  0  0  0 a4 a3 a2     a1 a0 b5 b4 b3 b2 b1 b0     

                 pDes[1]                     pDes[0]

这看起来像是将三个值打包成6-5-5位结构的操作。