¿Cómo obtengo datos bit a bit de un valor entero en C?


Quiero extraer bits de un número decimal.

Por ejemplo, 7 es el binario 0111, y quiero obtener 0 1 1 1 todos los bits almacenados en bool. ¿Cómo puedo hacerlo?

OK, un bucle no es una buena opción, ¿puedo hacer algo más para esto?

Author: Peter Mortensen, 2010-02-12

8 answers

Si quieres el k-ésimo bit de n, entonces haz

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

Aquí creamos una máscara, aplicamos la máscara a n, y luego desplazamos a la derecha el valor enmascarado para obtener solo el bit que queremos. Podríamos escribirlo más completamente como:

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

Puede leer más sobre el enmascaramiento de bits aquí.

Aquí hay un programa:

#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");
}
 125
Author: forefinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-09 04:21:03

Como se me pidió, decidí extender mi comentario sobre la respuesta del dedo índice a una respuesta completa. Aunque su respuesta es correcta, es innecesariamente compleja. Además, todas las respuestas actuales usan ints firmados para representar los valores. Esto es peligroso, ya que el desplazamiento a la derecha de los valores negativos está definido por la implementación (es decir, no es portátil) y el desplazamiento a la izquierda puede conducir a un comportamiento indefinido (ver esta pregunta).

Desplazando a la derecha el bit deseado al bit menos significativo posición, el enmascaramiento se puede hacer con 1. No es necesario calcular un nuevo valor de máscara para cada bit.

(n >> k) & 1

Como un programa completo, computando (y posteriormente imprimiendo) una matriz de valores de un solo bit:

#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);
}

Suponiendo que desea calcular todos los bits como en este caso, y no uno específico, el bucle se puede cambiar a

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

Esto modifica input en su lugar y por lo tanto permite el uso de un ancho constante, desplazamiento de un solo bit, que puede ser más eficiente en algunos arquitectura.

 60
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:26

Aquí hay una manera de hacerlo-hay muchas otras:

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

for (int j = 0;  j < 4;  ++j)
   b [j] =  0 != (v & (1 << j));
 3
Author: wallyk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-12 04:55:47

Aquí hay una manera muy sencilla de hacerlo;

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;
}
 2
Author: d3vdpro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-01 18:58:48

@prateek gracias por su ayuda. Reescribí la función con comentarios para su uso en un programa. Aumente 8 para más bits (hasta 32 para un entero).

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;
}
 1
Author: xinthose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-24 18:52:01

Si no quieres bucles, tendrás que escribirlo:

#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;
}

Como se muestra aquí, esto también funciona en un inicializador.

 1
Author: wildplasser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-01 19:00:09

Usando std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
 1
Author: Smit Ycyken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 14:47:03
#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;
}
 0
Author: anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-22 19:09:24