Подтвердить что ты не робот

Побитовый оператор для получения байта из 32 бит

Мне интересно написать функцию getMyByteChunkFunction, которая принимает два параметра - 32-разрядное целое и смещение байтов (0, 1, 2 или 3), затем возвращает соответствующий байт из 32-битного целого числа, Например, учитывая это целое число:

            (3)         (2)      (1)      (0)   ---byte numbers
int word = 10101010 00001001 11001010 00000101

вызов функции getMeByteChunkFunction(word, 2) возвращает 00001001.

Однако я ограничен в побитовых операциях, которые я могу использовать. Мне разрешено использовать >>, << и ровно одно вычитание. Я знаю, как это сделать с помощью AND и XOR, но я не знаю, как использовать здесь вычитание. Любые идеи?

4b9b3361

Ответ 1

Одна идея заключается в следующем. Предположим, что у вас есть четырехбайтное значение, подобное этому:

aaaaaaaa bbbbbbbb cccccccc dddddddd

Предположим, что вы хотите получить из этого байта bbbbbbbb. Если вы сдвигаетесь вправо на два байта, вы получаете

???????? ???????? aaaaaaaa bbbbbbbb

Это значение равно тому, что вы хотите, за исключением того, что вверху он имеет ???????? ???????? aaaaaaaa (потому что мы не уверены, что сдвиг сохраняет знак или нет, так как я не знаю, является ли ваше значение беззнаковым или нет). Однако не стоит беспокоиться; мы можем избавиться от этих неизвестных значений и байт a. Чтобы избавиться от вершины, предположим, что вы смещаете правый другой байт, предоставляя

???????? ???????? ???????? aaaaaaaa

Теперь сдвиньте один байт, чтобы получить

???????? ???????? aaaaaaaa 00000000

Если вы сделаете это вычитание, вы получите

    ???????? ???????? aaaaaaaa bbbbbbbb
-   ???????? ???????? aaaaaaaa 00000000
---------------------------------------
    00000000 00000000 00000000 bbbbbbbb

И все, что вам нужно...

Я оставлю фактический код в качестве упражнения для читателя. Не волнуйся; это не особенно сложно.: -)

Ответ 2

Вы можете сделать это просто с переходом. Сдвиньте влево, чтобы избавиться от бит слева, затем сдвиньтесь вправо, чтобы избавиться от бит справа и переместить желаемый байт в наименее значимое место.

Ответ 3

Следующий код также должен ответить на вопрос.

#include <stdio.h>

int getByte(int x, int n);

void main()
{
    int x = 0xAABBCCDD;
    int n;

    for (n=0; n<=3; n++) {
        printf("byte %d of 0x%X is 0x%X\n",n,x,getByte(x,n));
    }

}

// extract byte n from word x
// bytes numbered from 0 (LSByte) to 3 (MSByte)
int getByte(int x, int n)
{
    return (x >> (n << 3)) & 0xFF;
}

Выходной сигнал

byte 0 of 0xAABBCCDD is 0xDD
byte 1 of 0xAABBCCDD is 0xCC
byte 2 of 0xAABBCCDD is 0xBB
byte 3 of 0xAABBCCDD is 0xAA

Концепция может быть объяснена на основе templatetypedef объяснения и расширена следующим образом.

(3)      (2)      (1)      (0)
aaaaaaaa bbbbbbbb cccccccc dddddddd

{(3),(2),(1),(0)} --> {(3)}
  ???????? ???????? ???????? aaaaaaaa // x>>(3*8) where 3 == n
& 00000000 00000000 00000000 11111111 // 0xFF
  -----------------------------------
  00000000 00000000 00000000 aaaaaaaa // (x >> (8 * n)) & 0xFF

{(3),(2),(1),(0)} --> {(2)}
  ???????? ???????? aaaaaaaa bbbbbbbb // x>>(2*8) where 2 == n
& 00000000 00000000 00000000 11111111 // 0xFF  
  -----------------------------------
  00000000 00000000 00000000 bbbbbbbb

{(3),(2),(1),(0)} --> {(1)}
  ???????? aaaaaaaa bbbbbbbb cccccccc // x>>(1*8) where 1 == n
& 00000000 00000000 00000000 11111111 // 0xFF  
  -----------------------------------
  00000000 00000000 00000000 cccccccc

{(3),(2),(1),(0)} --> {(0)}
  aaaaaaaa bbbbbbbb cccccccc dddddddd // x>>(0*8) where 0 == n
& 00000000 00000000 00000000 11111111 // 0xFF  
  -----------------------------------
  00000000 00000000 00000000 dddddddd

Note (x >> (8 * n)) & 0xFF is equivalent to (x >> (n << 3)) & 0xFF.

64 32 16 8 4 2 1 
----------------
0  0  0  0 0 1 1 // (n==3)
0  0  1  1 0 0 0 // (n*8==n<<3==24)
----------------
0  0  0  0 0 1 0 // (n==2)
0  0  1  0 0 0 0 // (n*8==n<<3==16)
----------------
0  0  0  0 0 0 1 // (n==1)
0  0  0  1 0 0 0 // (n*8==n<<3==8)
----------------

Ответ 4

result = (word >> (n_byte << 3)) & 0xFF;

Ответ 5

Здесь очень умный трюк, который я использую для преобразования объектов в строки char (для передачи в виде потока):

//WhichByte should really be an enum to avoid issues
//Counts as 0, 1, 2 or 3
//Modify as unsigned or signed char (for return type and pointer type) as needed
#define BYTE_TYPE unsigned char
BYTE_TYPE GetByte(const unsigned int Source, const unsigned char WhichByte)
{
    if(WhichByte < 0){return 0;}
    if(WhichByte >= sizeof(Source)){return 0;}

    //Converts source into the appropriate pointer
    BYTE_TYPE * C_Ptr = (BYTE_TYPE *)&Source;
    return *(C_Ptr+WhichByte);
}
#undef BYTE_TYPE

Вкратце, вышеупомянутое рассматривает источник как 4 отдельных символа (размер которых обычно равен 1 байт), и указатель позволяет вам рассматривать его как раздел памяти. Вы разыгрываете его перед возвращением.

Используйте его независимо от цели (даже коммерческой).

Сжатый формат?

#define GetByte(X,Y) (*(((unsigned char *)&X)+Y))

Ответ 6

вот код:

#include <stdio.h>

int main() {
    unsigned long n = 0xAA09CA05L; /* 10101010 00001001 11001010 00000101 */
    printf("%08lx\n", n); /* input */
    printf("%02lx\n", ((n<<8)>>24)); /* output */
    return 0;
}

и вывод:

aa09ca05
09