C语言 查找无符号32位整数中的位位置

mspsb9vt  于 2023-02-11  发布在  其他
关注(0)|答案(9)|浏览(198)

我想我可能在CS课上睡着了,当他们谈论位位置的时候,所以我希望有人能帮上忙。
我有一个无符号32位整数(让我们使用该值:二十八)
根据我正在阅读的一些文档,整数的值包含指定各种事情的标志。
标志内的位位置从1(低位)到32(高位)编号。所有未定义的标志位均保留,必须设置为0。
我有一个表,显示了标志的含义,数字1 - 10的含义。
我希望有人能试着向我解释这一切意味着什么,以及如何从一个像28这样的数字中找到"标志"值。
谢谢

vlf7wbxs

vlf7wbxs1#

您可以只循环已设置的位,而不是循环每一位,如果您希望位被稀疏地设置,这样会更快:
假设位字段在(标量整数)变量字段中。

while (field){
  temp = field & -field;  //extract least significant bit on a 2s complement machine
  field ^= temp;  // toggle the bit off
  //now you could have a switch statement or bunch of conditionals to test temp
  //or get the index of the bit and index into a jump table, etc.
}

当位字段的大小不受单一数据类型的限制,而是可以是任意大小时,这种方法非常有效,在这种情况下,您可以一次提取32位(或任何寄存器大小),并针对0进行测试,然后继续处理下一个字。

envsm3lx

envsm3lx2#

要获取值为01int,其中01仅表示该整数的第n位,请用途:

int bitN = (value >> n) & 1;

但这通常不是你想做的,更常见的一个成语是:

int bitN = value & (1 << n);

在这种情况下,如果第n位未置位,则bitN0,如果第n位置位,则bitN为非零值(具体地说,它将是仅第n位置位后得出的任何值)。

xe55xuns

xe55xuns3#

假设flags是无符号的...

int flag_num = 1;
while (flags != 0)
{
    if ((flags&1) != 0)
    {
        printf("Flag %d set\n", flags);
    }
    flags >>= 1;
    flag_num += 1;
}

如果flags有符号,则应将

flags >>= 1;

flags = (flags >> 1) & 0x7fffffff;
zf2sa74q

zf2sa74q4#

使用一个log函数,以2为基数,在python中如下所示:

import math 

position = math.log(value, 2)

如果位置不是整数,则超过1位被设置为1。

dauxcl2d

dauxcl2d5#

@invaliddata的回答略有不同-

unsigned int tmp_bitmap = x;        
while (tmp_bitmap > 0) {
    int next_psn = __builtin_ffs(tmp_bitmap) - 1;
    tmp_bitmap &= (tmp_bitmap-1);
    printf("Flag: %d set\n", next_psn);
}
2ledvvac

2ledvvac6#

// You can check the bit set positions of 32 bit integer.
// That's why the check is added "i != 0 && i <= val" to iterate till 
// the end bit position.
    void find_bit_pos(unsigned int val) {
            unsigned int i;
            int bit_pos;
            printf("%u::\n", val);
            for(i = 1, bit_pos = 1; i != 0 && i <= val; i <<= 1, bit_pos++) { 
                    if(val & i)
                            printf("set bit pos: %d\n", bit_pos);
            }
    }
mtb9vblg

mtb9vblg7#

@boolAeon答案的MSVC变体

#include <vector>
#include <intrin.h>

std::vector<unsigned long> poppos(const unsigned long input)
{
    std::vector<unsigned long> result;
    result.reserve(sizeof(input) * CHAR_BIT);

    unsigned long num = input;
    unsigned long index = -1;

    while (_BitScanForward(&index, num))
    {
        result.push_back(index);
        num &= num - 1;
    }

    return result;
}
eyh26e7m

eyh26e7m8#

假设你有一个整数数组,你想找到所有的位置(32位位置),这些位置的位被设置在一起,也就是说,对于一个特定的位位置,通过考虑所有的整数,你总共会有多少个设置位。在这种情况下,你可以做的是检查每个整数,并标记其设置位位置:

// let arr[n] is an array of integers of size n.
int fq[33] = {0} // frequency array that will contain frequency of set bits at a particular position as 1 based indexing.
for(int i=0; i<n; i++) {
   int x = arr[i];
   int pos = 1; // bit position
   for(int i=1; i<=pow(2,32); i= i<<1) {  // i is the bit mask for checking every position and will go till 2^32 because x is an integer.
      if(x & i) fq[pos]++;
      pos++;
   }
}
x3naxklr

x3naxklr9#

28转换为二进制的11100。这意味着位1和2未置位,而位3、4和5置位。
有几点:首先,任何真正熟悉C语言的人通常都会从0开始编号,而不是从1开始。其次,您可以使用按位AND运算符(&)测试各个标志,如下所示:

#define flag1 1    //  1 = 00 0001
#define flag2 2    //  2 = 00 0010
#define flag3 4    //  4 = 00 0100
#define flag4 8    //  8 = 00 1000
#define flag5 16   // 16 = 01 0000
#define flag6 32   // 32 = 10 0000

if (myvalue & flag1)
    // flag1 was set

if (myvalue & flag4)
    // flag4 was set

等等。您还可以检查在循环中设置了哪些位:

#include <stdio.h>

int main() { 
    int myvalue = 28;
    int i, iter;

    for (i=1, iter=1; i<256; i<<=1, iter++)
        if (myvalue & i)
            printf("Flag: %d set\n", iter);
    return 0;
}

应打印:

Flag: 3 set
Flag: 4 set
Flag: 5 set

相关问题