如何从32位数中提取位

时间:2014-02-03 23:42:16

标签: binary hex extract bits

由于我的一位同事正在休假,我对C语言并不了解,因此我遇到了问题。

我有一个32位的数字,我必须从中提取位。我确实经历了几个线程,但我仍然不清楚如何这样做。如果有人可以帮助我,我将非常感激。

以下是我需要做的一个例子:

假设十六进制数= 0xD7448EAB。 二进制= 1101 01 11 0100 0100 1000 11 10 1010 1011 我需要提取16位,然后输出该值。我想要第10到25位。

忽略低10位(十进制)。即10 1010 1011被忽略 并且忽略高6位(溢出)。即,1101 01被忽略。

其余16位数据需要输出为11 0100 0100 1000(需要斜体数字作为输出)。

这是一个例子,但我将一直保持不同的十六进制数字,我需要提取与我解释的相同的位。

我如何解决这个问题?

谢谢。

对于此示例,您将输出1101 0001 0010 0011,即0xD123或53,539十进制。

4 个答案:

答案 0 :(得分:3)

好的,这是我写的方式:

#include <stdint.h>
#include <stdio.h>

main() {
    uint32_t in = 0xd7448eab;
    uint16_t out = 0;

    out = in >> 10; // Shift right 10 bits
    out &= 0xffff;  // Only lower 16 bits
    printf("%x\n",out);
}

in >> 10将数字右移10位; & 0xffff丢弃除低16位以外的所有位。

答案 1 :(得分:2)

您需要掩码来获取所需的位。 Masks 是您可以用来以您想要的方式筛选位的数字(保留位,删除/清除位,修改数字等)。您需要知道的是 AND,OR,XOR,NOT和移位操作。根据您的需要,您只需要一对夫妇。

你知道转移: x << y 将位从 x * y位置移动到左边*。

如何按顺序将x位设置为1: (1 << x) - 1

如何将x位按顺序设置为1,从y开始到y + x: ((1 << x) -1) << y

以上是您需要的位掩码。因此,例如,如果您想要16位0xD7448EAB,从10到25,您需要上述内容,因为x = 16且y = 10.

现在要获得你想要的位,只需 AND 使用上面的掩码编号0xD7448EAB,你就可以得到掩码 0xD7448EAB只有你的位想。之后,如果您想要浏览每一个,您需要将结果向右移动10并一次处理每个位(位置0)。

答案可能会更长一些,但它的设计要好于使用0xff或其他任何方式进行硬编码。

答案 2 :(得分:1)

  

我想要第10到25位。

你可以这样做:

unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;

或者这个:

unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;

答案 3 :(得分:1)

我将上面的前2个答案结合起来编写了一个C程序,它提取32位无符号整数的任何比特范围(不仅仅是10到25)的位。函数的工作方式是将lo的位hi返回到num的{​​{1}}。

#include <stdio.h>
#include <stdint.h>

unsigned extract(unsigned num, unsigned hi, unsigned lo) {
    uint32_t range = (hi - lo + 1);  //number of bits to be extracted
    //shifting a number by the number of bits it has produces inconsistent 
    //results across machines so we need a special case for extract(num, 31, 0)
    if(range == 32)
        return num;
    uint32_t result = 0;
    //following the rule above, ((1 << x) - 1) << y) makes the mask:
    uint32_t mask = ((1 << range) -1) << lo;
    //AND num and mask to get only the bits in our range
    result = num & mask;
    result = result >> lo; //gets rid of trailing 0s
    return result;
}
int main() {
    unsigned int num = 0xd7448eab;
    printf("0x%x\n", extract(num, 10, 25));
}