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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3142867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:46:23  来源:igfitidea点击:

Finding Bit Positions in an unsigned 32-bit integer

cbit-manipulation

提问by kdbdallas

I think I might have been asleep in my CS class when they talked about Bit Positions, so I am hoping someone can lend a hand.

当他们谈论 Bit Positions 时,我想我可能在 CS 课上睡着了,所以我希望有人能伸出援手。

I have a unsigned 32-bit integer (Lets use the value: 28)

我有一个无符号的 32 位整数(让我们使用值:28)

According to some documentation I am going over, the value of the integer contains flags specifying various things.

根据我正在阅读的一些文档,整数的值包含指定各种事物的标志。

Bit positions within the flag are numbered from 1 (low-order) to 32 (high-order). All undefined flag bits are reserved and must be set to 0.

标志内的位位置从 1(低位)到 32(高位)编号。所有未定义的标志位都是保留的,必须设置为 0。

I have a Table that shows the meanings of the flags, with meaning for the numbers 1-10.

我有一个表格,显示了标志的含义,其中数字 1-10 的含义。

I am hoping that someone can try and explain to me what this all means and how to find the "flag" value(s) from a number like, 28, based off of bit position.

我希望有人可以尝试向我解释这一切意味着什么以及如何根据位位置从诸如 28 之类的数字中找到“标志”值。

Thanks

谢谢

回答by Jerry Coffin

28 converts to 11100 in binary. That means bits 1 and 2 are not set and bits 3, 4 and 5 are set.

28 转换为二进制的 11100。这意味着第 1 位和第 2 位未设置,而第 3、4 和 5 位已设置。

A few points: first, anybody who's really accustomed to C will usually start the numbering at 0, not 1. Second, you can test of individual flags with the bitwise and operator (&), as in:

几点:首先,任何真正习惯 C 的人通常会从 0 开始编号,而不是 1。其次,您可以使用按位和运算符 ( &)测试各个标志,如下所示:

#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

and so on. You can also check which bits are set in a loop:

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

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

should print:

应该打印:

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

回答by invaliddata

Instead of looping through every single bit, you can instead loop through only the set bits, which can be faster if you expect bits to be sparsely set:

您可以只循环设置位,而不是遍历每一位,如果您希望位设置为稀疏,则速度会更快:

Assume the bit field is in (scalar integer) variable field.

假设位字段在(标量整数)变量字段中。

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

Works pretty well when the bit field is not limited to the size of a single data type, but could be of some arbitrary size. In that case, you can extract 32 (or whatever your register size is) bits at a time, test it against 0, and then move on to the next word.

当位域不限于单个数据类型的大小,但可以是任意大小时,效果很好。在这种情况下,您可以一次提取 32(或任何您的寄存器大小)位,针对 0 对其进行测试,然后移至下一个字。

回答by JSB????

To get an intwith the value 0or 1representing just the nth bit from that integer, use:

要获得int具有值01仅表示n该整数的第 th 位的 ,请使用:

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

But that's not usually what you want to do. A more common idiom is this:

但这通常不是您想要做的。一个更常见的成语是这样的:

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

In this case bitNwill be 0if the nth bit is not set, and non-zero in the case that the nth bit is set. (Specifically, it'll be whatever value comes out with just the nth bit set.)

在这种情况下bitN将是0如果n个位没有设置,并且在情况不为零,该n位被设置。(具体来说,它将是仅设置n第 th 位的任何值。)

回答by Doug Currie

Assuming flagsis unsigned...

假设flags未签名...

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

If flagsis signed you should replace

如果flags已签名,则应更换

flags >>= 1;

with

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

回答by user2593263

Use a log function, with base 2. In python, that would look like:

使用基数为 2 的日志函数。在 python 中,它看起来像:

import math 

position = math.log(value, 2)

If position is not an integer, then more than 1 bit was set to 1.

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

回答by boolAeon

A slight variation of @invaliddata's answer-

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

回答by Chandrakant Agarkar

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