Pytanie W jaki sposób uzyskać dane bit-by-bitowe z wartości całkowitej w C?


Chcę wyodrębnić bity liczby dziesiętnej.

Na przykład 7 jest binarnym 0111, a ja chcę uzyskać 0 1 1 1 wszystkie bity przechowywane w Bool. Jak mogę to zrobić?

OK, pętla nie jest dobrym rozwiązaniem, czy mogę zrobić coś innego?


76
2018-02-12 04:51


pochodzenie




Odpowiedzi:


Jeśli chcesz k-tego bitu n, to zrób

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

Tutaj tworzymy maskę, nakładamy maskę na n, a następnie przesuwając w prawo zamaskowaną wartość, aby uzyskać tylko żądany fragment. Możemy napisać to pełniej, jako:

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

Możesz przeczytać więcej o maskowaniu bitów tutaj.

Oto program:

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

120
2018-02-12 04:54



(n >> k) & 1 jest równie ważny i nie wymaga obliczenia maski, ponieważ maska ​​jest stała ze względu na przesuwanie przed maskowaniem zamiast na odwrót. - Joe
@Joe, czy możesz wyjaśnić to, być może w odpowiedzi, proszę? - Dan Rosenstark
@Yar nieco rozszerzyłem mój komentarz i dodałem nową odpowiedź zgodnie z życzeniem - Joe
Używając znanych bitów do informacji (tj. Do protokołów sieciowych, takich jak Websockets), rzutując dane na struct może być również użyteczny, ponieważ wszystkie wymagane dane można uzyskać za pomocą pojedynczej operacji. - Myst
@finger, czy możesz podać przykładowy kod wyjściowy. - Ashish Ahuja


Zgodnie z prośbą, postanowiłem rozszerzyć mój komentarz na odpowiedź palcem wskazującym na pełną odpowiedź. Chociaż jego odpowiedź jest poprawna, jest niepotrzebnie złożona. Ponadto wszystkie aktualne odpowiedzi korzystają z podpisu ints do reprezentowania wartości. Jest to niebezpieczne, ponieważ prawostronne przesuwanie wartości ujemnych jest zdefiniowane w implementacji (tzn. Nie jest przenośne), a przesunięcie w lewo może prowadzić do niezdefiniowanego zachowania (patrz to pytanie).

Przesuwając w prawo żądany bit do najmniej znaczącej pozycji bitu, można wykonać maskowanie 1. Nie ma potrzeby obliczania nowej wartości maski dla każdego bitu.

(n >> k) & 1

Jako kompletny program, oblicza (a następnie drukuje) tablicę wartości jednobitowych:

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

Zakładając, że chcesz obliczyć wszystkie bity, jak w tym przypadku, a nie konkretny, pętlę można dodatkowo zmienić na

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

To modyfikuje input w miejscu, a tym samym pozwala na stosowanie stałej szerokości, przesunięcia jednobitowego, które może być bardziej wydajne w niektórych architekturach.


57
2017-10-07 07:16





Oto jeden sposób, aby to zrobić - jest wiele innych:

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

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

3
2018-02-12 04:55





Oto bardzo prosty sposób na zrobienie tego;

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
2018-02-12 05:02





@prateek dziękuję za pomoc. Przepisałem funkcję za pomocą komentarzy do użycia w programie. Zwiększ 8, aby uzyskać więcej bitów (do 32 dla liczby całkowitej).

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
2018-02-24 18:52





Jeśli nie chcesz żadnych pętli, musisz je zapisać:

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

Jak wykazano tutaj, działa to również w inicjalizatorze.


1
2018-05-20 11:17





Za pomocą std::bitset

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

1
2018-05-12 14:47





#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
2018-05-20 02:55