如何在C中创建最低有效位设置为1的掩码
有人能给我解释一下这个功能吗 最低有效n位设置为1的掩码 例: n=6-->0x2F,n=17-->0x1fff//我根本不懂这些,尤其是n=6-->0x2F的用法如何在C中创建最低有效位设置为1的掩码,c,bit-manipulation,bitmask,C,Bit Manipulation,Bitmask,有人能给我解释一下这个功能吗 最低有效n位设置为1的掩码 例: n=6-->0x2F,n=17-->0x1fff//我根本不懂这些,尤其是n=6-->0x2F的用法 还有,什么是掩码?通常的方法是取一个1,然后将其左移n位。这将为您提供如下信息:00100000。然后从中减去一,这将清除设置的位,并设置所有低有效位,因此在本例中,我们得到:0001111 掩码通常用于按位操作,尤其是和。您可以使用上面的掩码自己获取5个最低有效位,与可能存在的任何其他位隔离。这在处理通常具有单个硬件寄存器的硬件时
还有,什么是掩码?通常的方法是取一个
1
,然后将其左移n
位。这将为您提供如下信息:00100000
。然后从中减去一,这将清除设置的位,并设置所有低有效位,因此在本例中,我们得到:0001111
掩码通常用于按位操作,尤其是
和
。您可以使用上面的掩码自己获取5个最低有效位,与可能存在的任何其他位隔离。这在处理通常具有单个硬件寄存器的硬件时尤其常见,其中包含表示许多完全独立、不相关的量和/或标志的位。我认为您的第一个示例应该是0x3f
0x3f
是二进制数字63
的十六进制表示法,即111111
,因此最后6位(最低有效6位)设置为1
以下小C程序将计算正确的掩码:
#include <stdarg.h>
#include <stdio.h>
int mask_for_n_bits(int n)
{
int mask = 0;
for (int i = 0; i < n; ++i)
mask |= 1 << i;
return mask;
}
int main (int argc, char const *argv[])
{
printf("6: 0x%x\n17: 0x%x\n", mask_for_n_bits(6), mask_for_n_bits(17));
return 0;
}
#包括
#包括
位的整数掩码(整数n)
{
int-mask=0;
对于(int i=0;i 掩码|=10x2F
是二进制的0010 1111
——这应该是0x3f
,二进制的0011 1111
,并且设置了6个最低有效位
类似地,0x1fff
是二进制的0001 1111 1111 1111 1111
,它设置了17个最低有效位
“掩码”是一个值,它打算与另一个值结合使用逐位运算符,如&
、|
或^
来单独设置、取消设置、翻转或保持该另一个值中的位不变
例如,如果使用&
运算符将掩码0x2F
与某个值n
组合,则结果中除6个最低有效位外,其余所有位都将为零,并且这6个位将从值n
复制而不改变
在和掩码的情况下,掩码中的二进制0
表示“无条件地将结果位设置为0”,而1
表示“将结果位设置为输入值位”。对于
掩码,掩码中的0
将结果位设置为输入位,1
无条件地将结果位设置为1
,对于^
掩码,0
将结果位设置为输入位,1
将结果位设置为输入位的补码。ak是一个常用术语,表示与另一个整数值按位AND、OR、XOR等运算的整数值
例如,如果要提取int变量的8个最低有效位,则需要执行variable&0xFF
。0xFF是一个掩码
同样,如果要设置位0和8,则需要设置变量| 0x101
,其中0x101是掩码
或者,如果要反转相同的位,可以执行变量^0x101
,其中0x101是掩码
要为您的案例生成掩码,您应该利用一个简单的数学事实,即如果将1添加到掩码中(掩码的所有最低有效位设置为1,其余位设置为0),您将得到一个2的幂
所以,如果你产生了最接近的2次方,那么你可以从中减去1得到遮罩
对于正确性和性能而言,使用左移可以很容易地生成2的正幂,实现这一点的最佳方法已经改变,因为在2012年,由于现代x86处理器(特别是BLSMSK)中出现了BMI指令,这个问题被问到
这里有一个解决这个问题的好方法,同时保持与旧处理器的向后兼容性
此方法是正确的,而当前的顶级答案在边缘情况下会产生未定义的行为
当允许使用BMI指令进行优化时,Clang和GCC将把gen_mask()压缩为两个操作。使用支持的硬件,请确保为BMI指令添加编译器标志:
-mbmi-mbmi2
#include <inttypes.h>
#include <stdio.h>
uint64_t gen_mask(const uint_fast8_t msb) {
const uint64_t src = (uint64_t)1 << msb;
return (src - 1) ^ src;
}
int main() {
uint_fast8_t msb;
for (msb = 0; msb < 64; ++msb) {
printf("%016" PRIx64 "\n", gen_mask(msb));
}
return 0;
}
#包括
#包括
uint64生成掩码(常数快速8最大有效位){
const uint64_t src=(uint64_t)1首先,对于那些只希望代码创建掩码的人:
uint64_t bits = 6;
uint64_t mask = ((uint64_t)1 << bits) - 1;
# Results in 0b111111 (or 0x03F)
uint64位=6;
uint64_t掩码=((uint64_t)1什么是掩码?顺便说一下,0x2F是错误的,应该是0x3f@chriswiki太混乱了…可能是重复的请记住,1完全正确。归咎于Intel,但它达到了standard.Ops。更新后编辑错误,但我确实回滚了。抱歉!抱歉,这是一个误解:我会使用宽度作为p参数(如OP提到的N),但由于使用了MSB的索引,它实际上是一致的。在这种情况下,consting做了什么?我认为@UlrichEckhardt的意思是,如果MSB定义了包含的最高有效位(这是典型用法),则掩码太短1位。根据包含性定义,1的msb应选择位1和0,因此掩码为0x3,但代码生成0x1。src=1LL,因为输入已移位1。此解决方案适用于所有位集(msb==63
),但您不能再请求未设置位的掩码,因为msb==0
将为您提供底部位集。