[英]Extract the first n bits of an unsigned int in C
I want to write a function which extracts the first n bits starting by the MSB of a given uint16.我想编写一个函数来提取从给定 uint16 的 MSB 开始的前 n 位。 I'm working with bitmasks for the first time and haven't found an elegant solution as far.
我第一次使用位掩码,到目前为止还没有找到一个优雅的解决方案。 I've written a similar function for the last n bits starting by the LSB which uses a bitmask looking like
我已经为 LSB 开始的最后 n 位编写了一个类似的函数,它使用的位掩码看起来像
(1 << n) - 1
and think this works.并认为这有效。
If I have the value 0b1010001100000101
my function creates the bitmask (for n = 3 it looks like 0b111
) and after that, uses the &-operator to check if the bits are present.如果我有值
0b1010001100000101
我的函数创建位掩码(对于 n = 3,它看起来像0b111
),然后使用 &-operator 检查位是否存在。
Which way should I use to get the first n bits?我应该使用哪种方式来获取前 n 位?
I would be really happy if someone explain this to me because I want to understand how it works.如果有人向我解释这一点,我会非常高兴,因为我想了解它是如何工作的。
Thank you!谢谢!
You do not need a mask to extract the most significant bits of an unsigned int
: just shift the value right by the width of the type less the number of bits:您不需要掩码来提取
unsigned int
的最高有效位:只需将值右移类型的宽度减去位数:
#include <stdint.h>
uint16_t extract_msbits(uint16_t x, int n) {
if (n <= 0)
return 0;
else
if (n < 16)
return x >> (16 - n);
else
return x;
}
If the extracted bits should stay in place, you really mean to mask off the lower bits.如果提取的位应该保留在原位,那么您的真正意思是屏蔽低位。 Here is a solution:
这是一个解决方案:
#include <limits.h>
uint16_t mask_msbits(uint16_t x, int n) {
if (n <= 0)
return 0;
else
if (n < 16)
return x & (~0U << (16 - n));
else
return x;
}
The expression (1 << n) - 1
has undefined behavior if n < 0
or n
is greater or equal to 15 if the width of int
is 16. For this reason, you should write (1U << n) - 1
to compute a mask for an unsigned int
or a uint16_t
, but it still fails on 16-bit systems if n
is 16 or larger, which might be a valid argument for the function.如果
n < 0
或n
大于或等于 15 如果int
的宽度为 16,则表达式(1 << n) - 1
具有未定义的行为。因此,您应该编写(1U << n) - 1
来计算unsigned int
或uint16_t
的掩码,但如果n
为 16 或更大,它在 16 位系统上仍然失败,这可能是函数的有效参数。 To avoid this issue, either use a test to compute a mask of 0xFFFF
for n == 16
or use (1UL << n) - 1
.为避免此问题,请使用测试为
n == 16
计算掩码0xFFFF
或使用(1UL << n) - 1
。
What you can do is to right shift your uint16_t
integral value, by 16 - n
bits.您可以做的是将您的
uint16_t
整数值右移16 - n
位。 Thus, only n
bits remain.因此,只剩下
n
位。
Assume you have a type uint16_t
and an integral object of this type with value 43558
named x
:假设您有一个类型
uint16_t
和一个此类型的整数对象,其值为43558
,名为x
:
uint16_t x = 43558U;
Right shifting by 16 - n
bits:右移
16 - n
位:
x >>= (16U - n);
// Or if you want to keep x intact
uint16_t y = x >> (16U - n);
Will store the first n
bits in x
.将前
n
位存储在x
中。 However, it will be padded with zeroes.但是,它将用零填充。 Therefore, you need to perform bitwise
AND
( &
) to test for the presence of 1
and 0
in this resulting x
.因此,您需要执行按位
AND
( &
) 来测试生成的x
中是否存在1
和0
。
If all you want is to mask off all but the top n
bits, you can simply shift right then left:如果您只想屏蔽除前
n
位之外的所有位,您可以简单地先右移再左移:
#include <assert.h>
#include <stdint.h>
/**
* @brief Masks all but top `n` bits
* @param number Input number
* @param n Number of bits to preserve. Must be >= 0 and <= 16
* @return Original number with all but the top `n` bits masked off
*/
uint16_t msb_n(uint16_t number, const unsigned n) {
assert(n <= 16 && "cannot shift more than 16 bits.");
number >>= (16 - n);
number <<= (16 - n);
return number;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.