如何在C中提取32位无符号整数的特定“n”位?

时间:2011-11-04 15:28:10

标签: c

有人能告诉我如何从C中的32位无符号整数中提取'n'特定位。

例如,假设我想要32位值的前17位;我应该做什么呢? 我认为我应该使用模数运算符并且我尝试了它并且能够获得最后8位和最后16位

unsigned last8bitsvalue=(32 bit integer) % 16
unsigned last16bitsvalue=(32 bit integer) % 32

这是对的吗?有没有更好,更有效的方法来做到这一点?

9 个答案:

答案 0 :(得分:41)

我不想将其视为“提取”,而是将其视为“孤立”。一旦所需的位被隔离,您就可以按照自己的意愿行事。

要隔离任何位组,请应用AND掩码。

如果你想要一个值的最后X位,可以使用一个简单的技巧。

unsigned  mask;
mask = (1 << X) - 1;
lastXbits = value & mask;

如果你想在'startBit'开始的'value'中间隔离一个X位...

unsigned  mask;
mask = ((1 << X) - 1) << startBit;
isolatedXbits = value & mask;

希望这有帮助。

答案 1 :(得分:27)

如果你想要n位特定的话,你可以先创建一个位掩码,然后用你的号码AND来获取所需的位。

从位a到位b创建掩码的简单功能。

unsigned createMask(unsigned a, unsigned b)
{
   unsigned r = 0;
   for (unsigned i=a; i<=b; i++)
       r |= 1 << i;

   return r;
}

你应该检查一个&lt; = b。

如果您想要第12到16位调用该功能,那么只需&amp; (逻辑AND)r,您的号码为N

r = createMask(12,16);
unsigned result = r & N;

如果您愿意,可以移动结果。希望这有帮助

答案 2 :(得分:8)

虽然我认为value & 0x1ffffvalue % 131072更直接地表示“占据底部17位”,但模数可以获得最低位(因为这样做)。

32位无符号值的前17位为value & 0xffff8000(如果您希望它们仍位于顶部的位置),或value >> 15如果您想要前17位值的最后17位结果。

答案 3 :(得分:7)

如果您需要整数的X位,请使用binary mask

unsigned last8bitsvalue=(32 bit integer) & 0xFF
unsigned last16bitsvalue=(32 bit integer) & 0xFFFF

答案 4 :(得分:4)

按位和您的整数,其掩码具有您想要提取的那些位。然后,如果需要,将结果右移以重新定位提取的位。

unsigned int lowest_17_bits = myuint32 & 0x1FFFF;
unsigned int highest_17_bits = (myuint32 & (0x1FFFF << (32 - 17))) >> (32 - 17);

编辑:后者将最高17位重新定位为最低17位;如果您需要从较大的“内”中提取整数,这可能很有用。如果不需要,您可以省略右移(>>)。

答案 5 :(得分:4)

在Intel和AMD CPU上有一条BEXTR (Bit field extract (with register)) x86指令,在ARM上有UBFX条指令。有一些内在函数,例如_bextr_u32()(链接需要登录),允许显式调用此指令。

他们实现(source >> offset) & ((1 << n) - 1) C代码:从n位开始从source获取offset个连续位。这是一个处理边缘情况的完整函数定义:

#include <limits.h>

unsigned getbits(unsigned value, unsigned offset, unsigned n)
{
  const unsigned max_n = CHAR_BIT * sizeof(unsigned);
  if (offset >= max_n)
    return 0; /* value is padded with infinite zeros on the left */
  value >>= offset; /* drop offset bits */
  if (n >= max_n)
    return value; /* all  bits requested */
  const unsigned mask = (1u << n) - 1; /* n '1's */
  return value & mask;
}

例如,要从3开始从22730b100011100001)获取5位,请致电getbits(2273, 5, 3) - 它会提取7(0b111 {1}})。

  

例如,假设我想要32位值的前17位;我应该做什么?

unsigned first_bits = value & ((1u << 17) - 1); // & 0x1ffff

假设您的系统CHAR_BIT * sizeof(unsigned)为32。

  

我认为我应该使用模数运算符并且我尝试了它并且能够获得最后8位和最后16位

unsigned last8bitsvalue  = value & ((1u <<  8) - 1); // & 0xff
unsigned last16bitsvalue = value & ((1u << 16) - 1); // & 0xffff

如果问题中的所有示例中的偏移量始终为零,则您不需要更通用的getbits()。有一个特殊的cpu指令BLSMSK可以帮助compute the mask ((1 << n) - 1)

答案 6 :(得分:2)

这是接受答案的简短变体:下面的函数通过创建位掩码从位到包含位提取位。在原始数字上应用AND逻辑后,结果将被移位,因此函数仅返回提取的位。 为清晰起见,跳过索引/完整性检查。

// get a reference to the app delegate
let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate

// call didFinishLaunchWithOptions ... why?
appDelegate?.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)

答案 7 :(得分:0)

int get_nbits(int num, int n)
{
return  (((1<<n)-1) & num);
}

答案 8 :(得分:-1)

#define GENERAL__GET_BITS_FROM_U8(source,lsb,msb) \
    ((uint8_t)((source) & \
        ((uint8_t)(((uint8_t)(0xFF >> ((uint8_t)(7-((uint8_t)(msb) & 7))))) & \
             ((uint8_t)(0xFF << ((uint8_t)(lsb) & 7)))))))

#define GENERAL__GET_BITS_FROM_U16(source,lsb,msb) \
    ((uint16_t)((source) & \
        ((uint16_t)(((uint16_t)(0xFFFF >> ((uint8_t)(15-((uint8_t)(msb) & 15))))) & \
            ((uint16_t)(0xFFFF << ((uint8_t)(lsb) & 15)))))))

#define GENERAL__GET_BITS_FROM_U32(source,lsb,msb) \
    ((uint32_t)((source) & \
        ((uint32_t)(((uint32_t)(0xFFFFFFFF >> ((uint8_t)(31-((uint8_t)(msb) & 31))))) & \
            ((uint32_t)(0xFFFFFFFF << ((uint8_t)(lsb) & 31)))))))