Cの整数値からビットごとのデータを取得するにはどうすればよいですか?


99

10進数のビットを抽出したい。

たとえば、7はバイナリ0111であり、boolに格納されているすべてのビットを0 1 1 1に取得したいとします。どうすればできますか?

OK、ループは良いオプションではありません、これのために何か他のことはできますか?

回答:


153

nのk番目のビットが必要な場合は、次のようにします。

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

70
(n >> k) & 1は等しく有効であり、逆にではなくマスキング前にシフトするためにマスクが一定であるため、マスクを計算する必要はありません。
ジョー

@ジョーは、おそらく答えでそれを説明できますか?
Dan Rosenstark、2014年

1
@Yarは私のコメントを少し拡張し、要求に応じて新しい回答を追加しました
Joe

既知のビットを情報(つまり、Websocketsなどのネットワークプロトコル)にstruct使用する場合、1回の操作で必要なすべてのデータを取得できるため、データをにキャストすることも役立ちます。
Myst

@forefinger、コードの出力例を投稿してください。
Ashish Ahuja

83

リクエストに応じて、人差し指の回答に関するコメントを本格的な回答に拡張することにしました。彼の答えは正しいですが、それは不必要に複雑です。さらに、現在のすべての回答でintは、値を表すために符号付きsを使用しています。負の値の右シフトは実装定義(つまり、移植不可能)であり、左シフトは未定義の動作につながる可能性があるため、これは危険です(この質問を参照)。

目的のビットを最下位ビット位置に右シフトすることにより、でマスキングを行うことができます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適切に変更され、それによって一定幅のシングルビットシフトの使用を可能にします。これは、一部のアーキテクチャではより効率的な場合があります。


5

これを行う1つの方法を次に示します。他にも多くの方法があります。

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

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

ループの使用が望ましくない理由を理解することは困難ですが、ループを展開するのは簡単です。

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

または、最後の4つのステートメントで定数式を評価します。

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

3

これを行う非常に簡単な方法を次に示します。

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助けてくれてありがとう プログラムで使用するために、関数をコメント付きで書き直しました。ビットを増やすには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;
}

1

ループが必要ない場合は、書き出す必要があります。

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

ここで示されているように、これは初期化子でも機能します。


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

使用する std::bitset

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

これは便利な方法ですが、例に問題があります。bitset <n>、nはビット数なので、sizeof(int)の使用法は間違っています。
Jerry Chou
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.