Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Установка бита беззнакового символа с другим битом другого беззнакового символа без условного

Автор вопроса: HeisenbugОтветов: 3

Я использую побитовое для включения и выключения битов следующим образом:

unsigned char myChar = ...some value
myChar |= 0x01 << N // turn on the N-th bit

myChar &= ~(0x01 << N) //turn off the N-th bit

Теперь предположим, что значение N известно, но операция установки/снятия зависит от значения бита другого беззнакового символа. С этого момента я делаю так:

if ((otherChar & (0x01 << M)) != 0)
{
    //M-th bit of otherChar is 1
    myChar |= 0x01 << N;
}else
{
    myChar &= ~(0x01 << N);
}

Это должна быть своего рода операция "перемещения бита" из беззнакового символа в другой.

Мой вопрос: есть ли способ сделать это без использования условного? (и без std::bitset тоже)

  • Когда вы говорите N-th bit, это считается с нуля? Nawaz 23.06.2012
  • да.. на основе нуля. Это актуально? Heisenbug 23.06.2012

cc++bit-manipulation

Ответы

Ответ 1 · рейтинг 3 · Jerry Coffin

Краткий ответ - да".

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

unsigned char bit = 1 << N;

myChar &= ~bit;             // Zero the bit without changing anything else
myChar |= otherChar & bit;  // copy the bit from the source to the destination.

Это предполагает, что вы хотите скопировать бит N из источника в бит N адресата. Если биты источника и назначения могут иметь разные смещения, все становится немного сложнее. Вы должны не только извлечь правильный бит из источника, но затем вам нужно переместить его в правильное место, а затем ИЛИ в место назначения. Основная идея примерно такая же, как и выше, но код для переключения немного утомителен. Проблема в том, что вы хотите сделать что-то вроде:

unsigned char temp = source & 1 << M;
temp <<= N - M;
dest |= temp;

Это будет работать нормально, если N> M, но если M> N, вы получите что-то вроде temp <<= -3;. Вам хотелось бы, чтобы сдвиг влево на -3 превратился в сдвиг вправо на 3, но это не то, что происходит, поэтому вам нужен некоторый условный код, чтобы получить абсолютное значение и выяснить, нужно ли сделать сдвиг вправо или влево, чтобы получить бит от источника в правильное место в месте назначения.

Ответ 2 · рейтинг 3 · Oliver Charlesworth

Одно из решений состоит в том, чтобы сначала всегда сбрасывать бит, а затем побитово или в соответственно смещенной и замаскированной версии otherChar.

Ответ 3 · рейтинг 3 · Mark Tolonen

Это читает бит from c1 и записывает его в бит to c2.

#include <stdio.h>

typedef unsigned char uchar;

uchar move_bit(uchar c1, int from, uchar c2, int to)
{
    int bit;
    bit = (c1 >> from) & 1;            /* Get the source bit as 0/1 value */
    c2 &= ~(1 << to);                  /* clear destination bit */
    return (uchar)(c2 | (bit << to));  /* set destination bit */
}

int main()
{
    printf("%02X\n",move_bit(0x84,3,0x42,5));
    printf("%02X\n",move_bit(0x81,0,0x03,7));
    printf("%02X\n",move_bit(0xEF,4,0xFF,6));
    return 0;
}

Результат:

42
83
BF

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы