如何从C中的整数值获取逐位数据?

时间:2010-02-12 04:51:48

标签: c bit-manipulation

我想提取十进制数字的位。

例如,7是二进制0111,我想得到0 1 1 1存储在bool中的所有位。我怎么能这样做?

好的,循环不是一个好选择,我可以为此做点什么吗?

7 个答案:

答案 0 :(得分:137)

如果你想要n的第k位,那么

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

这里我们创建一个蒙版,将蒙版应用于n,然后右移蒙版值以获得我们想要的位。我们可以更全面地写出来:

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

您可以阅读有关位屏蔽here的更多信息。

这是一个程序:

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

答案 1 :(得分:66)

根据要求,我决定将我对食指答案的评论延伸到一个完整的答案。虽然他的答案是正确的,但它是不必要的复杂。此外,所有当前答案都使用带符号的int来表示值。这很危险,因为负值的右移是实现定义的(即不可移植),左移可能导致未定义的行为(见this question)。

通过将所需位右移到最低有效位,可以使用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,从而允许使用恒定宽度的单比特移位,这在某些架构上可能更有效。

答案 2 :(得分:3)

这是一种方法 - 还有很多其他方法:

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

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

答案 3 :(得分:2)

这是一种非常简单的方法;

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

答案 4 :(得分: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;
}

如此处所示,这也适用于初始化程序。

答案 5 :(得分: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;
}

答案 6 :(得分: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;
}