Как я могу получить побитовые данные из целочисленного значения в C?

Я хочу извлечь биты десятичного числа.

Например, 7 является двоичным 0111, и я хочу получить 0 1 1 1 все биты, хранящиеся в bool. Как я могу это сделать?

ОК, цикл не очень хороший вариант, я могу сделать что-то еще для этого?

8 ответов

Решение

Если вы хотите k-й бит из n, тогда

(n & ( 1 << k )) >> k

Здесь мы создаем маску, применяем маску к n, а затем сдвигаем маску вправо, чтобы получить только тот бит, который нам нужен. Мы могли бы написать это более полно как:

    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;

Вы можете прочитать больше о битовой маскировке здесь.

Вот программа:

#include <stdio.h>
#include <stdlib.h>

int *get_bits(int n, int bitswanted){
  int *bits = malloc(sizeof(int) * bitswanted);

  int k;
  for(k=0; k<bitswanted; k++){
    int mask =  1 << k;
    int masked_n = n & mask;
    int thebit = masked_n >> k;
    bits[k] = thebit;
  }

  return bits;
}

int main(){
  int n=7;

  int  bitswanted = 5;

  int *bits = get_bits(n, bitswanted);

  printf("%d = ", n);

  int i;
  for(i=bitswanted-1; i>=0;i--){
    printf("%d ", bits[i]);
  }

  printf("\n");
}

В ответ на просьбу я решил расширить свой комментарий к ответу указательного пальца на полноценный ответ. Хотя его ответ правильный, он излишне сложен. Кроме того, все текущие ответы используют подписанные ints для представления значений. Это опасно, поскольку смещение вправо отрицательных значений определяется реализацией (т. Е. Не переносимо), а смещение влево может привести к неопределенному поведению (см. Этот вопрос).

Путем смещения правого бита в положение младшего бита маскирование можно выполнить с помощью 1, Нет необходимости вычислять новое значение маски для каждого бита.

(n >> k) & 1

В качестве полной программы, вычисляя (и впоследствии печатая) массив однобитовых значений:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    unsigned
        input = 0b0111u,
        n_bits = 4u,
        *bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
        bit = 0;

    for(bit = 0; bit < n_bits; ++bit)
        bits[bit] = (input >> bit) & 1;

    for(bit = n_bits; bit--;)
        printf("%u", bits[bit]);
    printf("\n");

    free(bits);
}

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

for(bit = 0; bit < n_bits; ++bit, input >>= 1)
    bits[bit] = input & 1;

Это изменяет input на месте и, таким образом, позволяет использовать однобитовый сдвиг постоянной ширины, что может быть более эффективным на некоторых архитектурах.

Вот один из способов сделать это - есть много других:

bool b[4];
int v = 7;  // number to dissect

for (int j = 0;  j < 4;  ++j)
   b [j] =  0 != (v & (1 << j));

Вот очень простой способ сделать это;

int main()
{
    int s=7,l=1;
    vector <bool> v;
    v.clear();
    while (l <= 4)
    {
        v.push_back(s%2);
        s /= 2;
        l++;
    }
    for (l=(v.size()-1); l >= 0; l--)
    {
        cout<<v[l]<<" ";
    }
    return 0;
}

С помощью std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();

Если вы не хотите никаких циклов, вам придется выписать это:

#include <stdio.h>
#include <stdbool.h>

int main(void)
{
    int num = 7;

    #if 0
        bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
    #else
        #define BTB(v,i) ((v) & (1u << (i))) ? true : false
        bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
        #undef BTB
    #endif

    printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);

    return 0;
}

Как показано здесь, это также работает в инициализаторе.

@Prateek спасибо за вашу помощь. Я переписал функцию с комментариями для использования в программе. Увеличьте 8 для большего количества битов (до 32 для целого числа).

std::vector <bool> bits_from_int (int integer)    // discern which bits of PLC codes are true
{
    std::vector <bool> bool_bits;

    // continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
    for (int i = 0; i < 8; i++)
    {
        bool_bits.push_back (integer%2);    // remainder of dividing by 2
        integer /= 2;    // integer equals itself divided by 2
    }

    return bool_bits;
}
#include <stdio.h>

int main(void)
{
    int number = 7; /* signed */
    int vbool[8 * sizeof(int)];
    int i;
        for (i = 0; i < 8 * sizeof(int); i++)
        {
            vbool[i] = number<<i < 0;   
            printf("%d", vbool[i]);
        }
    return 0;
}
Другие вопросы по тегам