Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中创建最低有效位设置为1的掩码_C_Bit Manipulation_Bitmask - Fatal编程技术网

如何在C中创建最低有效位设置为1的掩码

如何在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个最低有效位,与可能存在的任何其他位隔离。这在处理通常具有单个硬件寄存器的硬件时

有人能给我解释一下这个功能吗

最低有效n位设置为1的掩码

例:

n=6-->0x2F,n=17-->0x1fff//我根本不懂这些,尤其是n=6-->0x2F的用法


还有,什么是掩码?

通常的方法是取一个
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掩码|=1
0x2F
是二进制的
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
将为您提供底部位集。