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

hek*_*tor 30 c

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

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

unsigned last8bitsvalue=(32 bit integer) % 16
unsigned last16bitsvalue=(32 bit integer) % 32
Run Code Online (Sandbox Code Playgroud)

它是否正确?有没有更好,更有效的方法来做到这一点?

Spa*_*rky 41

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

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

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

unsigned  mask;
mask = (1 << X) - 1;
lastXbits = value & mask;
Run Code Online (Sandbox Code Playgroud)

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

unsigned  mask;
mask = ((1 << X) - 1) << startBit;
isolatedXbits = value & mask;
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


pne*_*zis 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;
}
Run Code Online (Sandbox Code Playgroud)

你应该检查一个<= b.

如果你想要第12到16位调用该函数,然后简单地&(逻辑AND)r你的号码N

r = createMask(12,16);
unsigned result = r & N;
Run Code Online (Sandbox Code Playgroud)

如果你想要你可以改变结果.希望这可以帮助

  • 没有必要花时间循环一个小面具.只是`((1 << n) - 1)<< b` (25认同)
  • 这更快并且对我也适用于`uint64_t`:`((1ull &lt;&lt; (b - a)) - 1ull) &lt;&lt; a` (2认同)

jfs*_*jfs 9

在 Intel 和 AMD CPU 以及ARM上有一条BEXTR(位域提取(带寄存器)) x86 指令UBFX。存在_bextr_u32()允许显式调用此指令的内在函数,例如(链接需要登录)。

他们实现了(source >> offset) & ((1 << n) - 1)C 代码:从nsource开始获得连续的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;
}
Run Code Online (Sandbox Code Playgroud)

例如,3要从2273( 0b100011100001) 中获取从5第 -th 位开始的位,请调用getbits(2273, 5, 3)— 它提取 7 ( 0b111)。

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

unsigned first_bits = value & ((1u << 17) - 1); // & 0x1ffff
Run Code Online (Sandbox Code Playgroud)

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

我想我应该使用模数运算符,我试了一下,能够得到最后 8 位和最后 16 位

unsigned last8bitsvalue  = value & ((1u <<  8) - 1); // & 0xff
unsigned last16bitsvalue = value & ((1u << 16) - 1); // & 0xffff
Run Code Online (Sandbox Code Playgroud)

如果在问题中的所有示例中偏移量始终为零,那么您不需要更一般的getbits(). 有一个特殊的 CPU 指令 BLSMSK 可以帮助计算掩码((1 << n) - 1)


Ste*_*sop 8

模数可以获得最低位(仅),虽然我认为value & 0x1ffff表达"比最低17位"更直接value % 131072,因此这样做更容易理解.

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


Céd*_*ien 7

如果需要整数的X最后一位,请使用二进制掩码:

unsigned last8bitsvalue=(32 bit integer) & 0xFF
unsigned last16bitsvalue=(32 bit integer) & 0xFFFF
Run Code Online (Sandbox Code Playgroud)


flo*_*ind 5

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

uint16_t extractInt(uint16_t orig16BitWord, unsigned from, unsigned to) 
{
  unsigned mask = ( (1<<(to-from+1))-1) << from;
  return (orig16BitWord & mask) >> from;
}
Run Code Online (Sandbox Code Playgroud)