C ++ бит манипуляции - PullRequest
       2

C ++ бит манипуляции

1 голос
/ 01 июля 2011

Я пытаюсь извлечь символьное значение из формата UTF-8. Предположим, у меня есть два символа, и я извлекаю 5 бит из первого символа => 10111 и 6 бит из другого символа => 010000

так

ch1 = 10111;
ch2 = 010000;

как бы я объединил их в форму 10111010000 и вывел ее гекс как 0x5d0? Нужно ли мне сдвигаться или есть более простой способ сделать это, потому что проверка документации write представляется способной читать символы последовательно, есть ли подобная функция, как эта? Кроме того, похоже, мне понадобится буфер символов, поскольку длина 10111010000 составляет 11 бит. Кто-нибудь знает, как это сделать?

Ответы [ 4 ]

3 голосов
/ 01 июля 2011

Вам необходимо использовать сдвиг, плюс оператор | или |=.

unsigned int ch3 = (ch1 << 6) | ch2;
// ch3 = 0000010111010000

Я предполагаю, что unsigned int составляет 16 бит. Ваш пробег может отличаться.

2 голосов
/ 01 июля 2011

Вам обязательно нужно будет использовать shift и OR.

Сначала объявите целочисленный тип без знака правильного размера.Мне нравятся типы C99, определенные в stdint.h, но ваш компилятор C ++ может их не иметь.Если у вас нет uint16_t, вы можете использовать unsigned short.Это 16 бит в ширину и может содержать 11 бит.

Тогда вы бы выяснили, какие биты входят в старшие биты.Похоже, что должно быть:

unsigned short ch1 = 0x17;
unsigned short ch2 = 0x10;
unsigned short result = (ch1 << 6) | ch2;
0 голосов
/ 01 июля 2011

Во-первых, от K & R: «Почти все в битовых полях зависит от реализации».

В MS Visual Studio 2008 работают следующие функции:

#include <stdio.h>
#include <string.h>

struct bitbag {
    unsigned int ch2 : 6;
    unsigned int ch1 : 6;
};

int main ()
{
    struct bitbag bits;

    memset(&bits, 0, sizeof(bits));

    bits.ch1 = 0x17;    // 010111
    bits.ch2 = 0x10;    // 010000

    printf ("0x%06x 0x%06x\n", bits.ch1, bits.ch2);
    printf ("0x%0x\n", bits);

    return 0;
}

Производит вывод:

0x000017 0x000010
0x5d0

Однако я не мог гарантировать, что он будет работать одинаково во всех компиляторах. Обратите внимание на memset, который инициализирует любой отступ до нуля.

0 голосов
/ 01 июля 2011

1: для объединения их вместе:

char bytes[2] = { 0x17, 0x10 }; // for example

unsigned short result = 0;      // 00000000  00000000
result = bytes[0] << 6;         // 101 11000000
result |= bytes[1];             // 101 11010000

2: для печати в шестнадцатеричном виде

std::cout << std::showbase << std::hex << <what you want to print>;

в данном случае:

std::cout << std::showbase << std::hex << result
// output: 0x5d0 if it is little-endian, it depends on your operating system
...