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

问题描述 投票:0回答:9

我想提取十进制数的位。

例如,7是二进制0111,我想获取bool中存储的所有位0 1 1 1。我怎样才能做到这一点?

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

c bit-manipulation
9个回答
204
投票

如果您想要 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");
}

108
投票

根据要求,我决定将我对食指答案的评论扩展为成熟的答案。尽管他的答案是正确的,但过于复杂。此外,所有当前答案都使用带符号的

int
来表示值。这是危险的,因为负值的右移是实现定义的(即不可移植),而左移可能导致未定义的行为(参见这个问题)。

通过将所需位右移到最低有效位位置,可以使用

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
,从而允许使用恒定宽度、单位移位,这在某些架构上可能更有效。


14
投票

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

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

或者计算最后四个语句中的常量表达式:

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

2
投票

使用

std::bitset

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

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

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
投票

如果你不想要任何循环,你必须把它写出来:

#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
投票

如果我可以重新表述这个问题,从整数中提取一组位的更一般的请求可以表述为:

我想从“pos”位开始的十进制数“n”中提取“size”位数,以便获得从位位置“pos + size”到“pos”开始的位

上面更一般的陈述可以表述为:

我想从位位置“pos”的十进制数“n”中提取 1 位

您可以将上面的语句更改为:

我想从十进制数“n”中一次提取一位并将其存储到布尔数组中,以便位位置“pos”对应于数组索引“pos”。

假设十进制数中位的第一个“位置”是LSB,即位0,我们可以像这样从十进制数中提取n位:

创建位数掩码:

(1 << size) - 1

将数字移位位数,以便索引处的位现在是 LSB :
n >> pos

使用掩码对移位后的值进行逻辑与:
(n >> pos) & ((1 << size) - 1) 

这是一个例子:

#define GET_N_BITS(n, size, pos, ret) ({ \
        ret = (n >> pos) & ((1 << size) - 1); \
)}

main()
{
        int n = 7;
        int extracted_bits = 0;
        // extract 2 bits from bit 1 onwards from decimal number 7
        GET_N_BITS(n, 2, 1, extracted_bits);
        // extracted bits = b0011 = 3
}

然后我们可以更改上面的内容,从给定的位位置提取并返回一位并将其存储在数组中。

#define GET_NTH_BIT(n, pos) ({ \
        bool ret; \
        ret = (n >> pos) & 1 \
        ret; \
})

main()
{
        int n = 7, i = 0;
        bool n_bit_by_bit[32];
        for (i = 0 ; i < 32 ; i++)
                n_bit_by_bit[i] = GET_NTH_BIT(n, i);
}
© www.soinside.com 2019 - 2024. All rights reserved.