Вопрос о побитовых операциях А и Shift - PullRequest
1 голос
/ 14 июля 2010

Как именно работают следующие строки, если pData = "abc"?

pDes[1] = ( pData[0] & 0x1c ) >> 2;
pDes[0] = ( pData[0] << 6 ) | ( pData[1] & 0x3f );

Ответы [ 4 ]

4 голосов
/ 14 июля 2010

Хорошо, при условии, что 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 то же самое, но смещение вправо.

Операция & (and) устанавливает каждый бит результата в 1, если и только если соответствующий бит на обоих входах равен 1.

Операции | (or) устанавливают каждый бит результата равным 1, если один или несколько соответствующих битов на обоих входах равны 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 на массив символов, вы получаете:

00000062 00000000
2 голосов
/ 14 июля 2010

& не логично И - это побитовое И.

a равно 0x61, поэтому pData[0] & 0x1c дает

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

>> 2 сдвигает это вправо на две позиции - значение не меняется, так как все биты равны нулю.

pData[0] << 6 сдвиги влево 0x61 на 6 бит, чтобы дать 01000000 или 0x40

pData[1] & 0x3f

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

Таким образом, все сводится к 0x40 | 0x22 - опять | не является логическим ИЛИ, оно является побитовым.

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

Результаты будут другими, если pDes не является массивом символов. Сдвиг влево 0x61 даст вам 0001 1000 0100 0000 или 0x1840 - (в случае, если pDes является массивом символов, левые части не на рисунке).

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

pDes[0] будет иметь значение 0x1862 или десятичное значение 6242.

1 голос
/ 14 июля 2010

C ++ будет обрабатывать символ как число в соответствии с его кодировкой.Таким образом, предполагая ASCII, «a» равно 97 (с битовой комбинацией 0110_0001), а «b» равно 98 (битовой комбинации 0110_0010).

Когда вы думаете о них как о числах, битовые операции над символами должныбыть немного яснее.

0 голосов
/ 14 июля 2010

В C все символы также являются целыми числами.Это означает, что "abc" эквивалентно (char[]){0x61, 0x62, 0x63, 0}.

. & - это , а не логический оператор 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 здесь - извлечь биты # 2 ~ # 4 из pData[0].>> 2 впоследствии удаляет лишние нули в конце.

Аналогично, & 0x3f предназначен для извлечения битов # 0 ~ # 5 из pData[1].

<< 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-битную структуру.

...