C'deki bir tamsayı değerinden bit bitlik verileri nasıl alırım?


99

Ondalık bir sayının bitlerini çıkarmak istiyorum.

Örneğin, 7 ikili 0111'dir ve bool'de depolanan tüm bitleri 0 1 1 1 elde etmek istiyorum. Bunu nasıl yapabilirim?

Tamam, döngü iyi bir seçenek değil, bunun için başka bir şey yapabilir miyim?

Yanıtlar:


154

K'inci n'yi istiyorsanız, yapın

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

Burada bir maske oluşturuyoruz, maskeyi n'ye uyguluyoruz ve sonra tam istediğimiz biti elde etmek için maskelenmiş değeri sağa kaydırıyoruz. Bunu daha eksiksiz bir şekilde yazabiliriz:

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

Sen bit maskeleme hakkında daha fazla bilgi bulabilirsiniz burada .

İşte bir 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");
}

70
(n >> k) & 1eşit derecede geçerlidir ve tam tersi yerine maskelemeden önce kayma nedeniyle maske sabit olduğundan maskenin hesaplanmasını gerektirmez.
Joe

@Joe bunu açıklayabilir misin, belki bir cevapla, lütfen?
Dan Rosenstark

1
@Yar yorumumu biraz uzattı ve istendiği gibi yeni bir cevap ekledi
Joe

Bilgi için bilinen bitleri kullanırken (yani, Websockets gibi ağ protokolleri için), structgerekli tüm verileri tek bir işlemle elde ettiğiniz için verileri bir a üzerine aktarmak da yararlı olabilir.
Myst

@forefinger, kodun örnek bir çıktısını gönderebilir misiniz?
Ashish Ahuja

83

İstendiği gibi, işaret parmağının cevabı hakkındaki yorumumu tam teşekküllü bir cevaba genişletmeye karar verdim. Cevabı doğru olsa da gereksiz yere karmaşıktır. Ayrıca tüm mevcut cevaplar int, değerleri temsil etmek için işaretli s kullanır. Negatif değerlerin sağa kaydırılması uygulama tanımlı olduğundan (yani taşınabilir değil) ve sola kaydırma tanımsız davranışa yol açabileceğinden ( bu soruya bakın) bu tehlikelidir .

İstenilen biti en az anlamlı bit konumuna sağa kaydırarak, maskeleme yapılabilir 1. Her bit için yeni bir maske değeri hesaplamaya gerek yoktur.

(n >> k) & 1

Tam bir program olarak, bir dizi tek bitlik değerleri hesaplamak (ve ardından yazdırmak):

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

Bu durumda olduğu gibi tüm bitleri hesaplamak istediğinizi ve belirli bir biti hesaplamak istemediğinizi varsayarsak, döngü daha sonra şu şekilde değiştirilebilir:

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

Bu input, yerinde değişiklik yapar ve böylece, bazı mimarilerde daha verimli olabilecek sabit genişlikte, tek bit kaymasının kullanımına izin verir.


5

İşte bunu yapmanın bir yolu - başka birçok yöntem var:

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

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

Bir döngü kullanımının neden istenmediğini anlamak zordur, ancak döngüyü açmak yeterince kolaydır:

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

Veya son dört ifadedeki sabit ifadeleri değerlendirmek:

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

3

İşte bunu yapmanın çok basit bir yolu;

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

1

@prateek yardımlarınız için teşekkür ederim. Fonksiyonu bir programda kullanılmak üzere yorumlarla yeniden yazdım. Daha fazla bit için 8'i artırın (bir tam sayı için 32'ye kadar).

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

Herhangi bir döngü istemiyorsanız, yazmanız gerekir:

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

Burada gösterildiği gibi, bu aynı zamanda bir başlatıcıda da çalışır.


0
#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

Kullanma std::bitset

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

Bu yararlı bir yöntem, ancak örnekte bir sorun var. bit kümesi <n>, n bit sayısıdır, bu nedenle sizeof (int) 'in kullanımı yanlıştır.
Jerry Chou
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.