有人能告诉我如何从C中的32位无符号整数中提取'n'特定位。
例如,假设我想要32位值的前17位;我应该做什么呢? 我认为我应该使用模数运算符并且我尝试了它并且能够获得最后8位和最后16位
unsigned last8bitsvalue=(32 bit integer) % 16
unsigned last16bitsvalue=(32 bit integer) % 32
这是对的吗?有没有更好,更有效的方法来做到这一点?
答案 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 & 0x1ffff
比value % 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
开始从2273
(0b100011100001
)获取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)))))))