web-dev-qa-db-fra.com

Comment obtenir des données bit par bit à partir d'une valeur entière en C?

Je veux extraire des bits d'un nombre décimal.

Par exemple, 7 est binaire 0111 et je souhaite obtenir 0 1 1 1 tous les bits stockés dans bool. Comment puis-je le faire?

OK, une boucle n'est pas une bonne option, puis-je faire autre chose pour cela?

93
Badr

Si vous voulez le k-ème bit de n, alors faites

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

Ici, nous créons un masque, appliquons le masque à n, puis décalons à droite la valeur masquée pour obtenir le bit souhaité. Nous pourrions l'écrire plus complètement comme:

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

Vous pouvez en savoir plus sur le masquage de bits ici .

Voici un programme:

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

Comme demandé, j'ai décidé d'étendre mon commentaire sur la réponse de l'index à une réponse à part entière. Bien que sa réponse soit correcte, elle est inutilement complexe. De plus, toutes les réponses actuelles utilisent ints signé pour représenter les valeurs. Ceci est dangereux car le décalage à droite des valeurs négatives est défini par la mise en œuvre (c’est-à-dire qu’il n’est pas transférable) et que le décalage à gauche peut conduire à un comportement indéfini (voir cette question ).

En déplaçant à droite le bit souhaité dans la position de bit le moins significatif, le masquage peut être effectué avec 1. Pas besoin de calculer une nouvelle valeur de masque pour chaque bit.

(n >> k) & 1

En tant que programme complet, calculant (puis imprimant) un tableau de valeurs à un seul 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);
}

En supposant que vous souhaitiez calculer tous les bits comme dans ce cas, et non un bit spécifique, vous pouvez modifier la boucle en

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

Ceci modifie input en place et permet ainsi l’utilisation d’un décalage à largeur constante et d’un bit, ce qui peut être plus efficace sur certaines architectures.

69
Joe

Voici une façon de le faire - il y en a beaucoup d'autres:

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

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

Il est difficile de comprendre pourquoi l’utilisation d’une boucle n’est pas souhaitée, mais il est assez facile de dérouler la boucle:

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

b [0] =  0 != (v & (1 << 0));
b [1] =  0 != (v & (1 << 1));
b [2] =  0 != (v & (1 << 2));
b [3] =  0 != (v & (1 << 3));

Ou évaluer des expressions constantes dans les quatre dernières déclarations:

b [0] =  0 != (v & 1);
b [1] =  0 != (v & 2);
b [2] =  0 != (v & 4);
b [3] =  0 != (v & 8);
4
wallyk

Voici un moyen très simple de le faire.

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;
}
3
d3vdpro

Si vous ne voulez pas de boucles, vous devrez l'écrire:

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

Comme démontré ici, cela fonctionne également dans un initialiseur.

1
wildplasser

@prateek merci pour votre aide. J'ai réécrit la fonction avec des commentaires pour une utilisation dans un programme. Augmentez 8 pour plus de bits (jusqu'à 32 pour un entier).

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
xinthose

En utilisant std::bitset

int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
1
Smit Ycyken
#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
anon