C中的位掩码

gri*_*igy 22 c bit-manipulation

在C中构造位掩码的最佳方法mk设置位,其前面是未设置位,后跟未n设置位:

00..0 11..1 00..0
  k     m     n
Run Code Online (Sandbox Code Playgroud)

例如,k = 1,m = 4,n = 3将导致位掩码:

01111000
Run Code Online (Sandbox Code Playgroud)

Dar*_*con 41

〜(〜0 << m)<< n

  • 这很光滑.但是,最好对这一行进行评论,让-next程序员对其进行处理. (2认同)
  • 如果将其编码为函数(@quinmar 答案中的 set_mask_n 函数),则会有一行注释说明该函数的作用(并且没有参数 'k'),并且该函数的用户将具有名称为文档。作为一些代码中的随机表达式,它无疑是糟糕的! (2认同)
  • "〜(~0 << m)"在Brian Kernighan和Dennis Ritchie的"C编程语言,第二版"的第2.9段"按位运算符"中.这也是Brian W. Kernighan和Rob Pike撰写的"编程实践"第7.5段"空间效率". (2认同)
  • 这种方法无法创建包含最长无符号整数类型的最高位的掩码,即通常用警告表示,例如预处理器表达式中的整数溢出。 (2认同)

Jon*_*ler 29

那么,你要求m个设置位前缀为k个复位位,后跟n个复位位?我们可以忽略k,因为它很大程度上受整数类型选择的约束.

mask = ((1 << m) - 1) << n;
Run Code Online (Sandbox Code Playgroud)

  • 它们都有效,但我发现乔纳森的答案更简单明了。大流士的回答对我来说有点过分了。 (2认同)

qui*_*ars 5

我喜欢这两种解决方案 这是我想到的另一种方式(可能不是更好).

((~((unsigned int)0) << k) >> (k + n)) << n

编辑:我以前的版本中有一个错误(没有unsigned int cast).问题是~0 >> n在前面添加1,而不是0.

是的,这种方法有一个很大的缺点; 它假设你知道默认整数类型的位数,或者换句话说它假设你真的知道k,而其他解决方案独立于k.这使我的版本不那么便携,或者至少难以移植.(它还使用3个移位,加法和按位求反运算符,这是两个额外的操作.)

所以你最好使用其他一个例子.

这是Jonathan Leffler完成的一个小测试应用程序,用于比较和验证不同解决方案的输出:

#include <stdio.h>
#include <limits.h>

enum { ULONG_BITS = (sizeof(unsigned long) * CHAR_BIT) };

static unsigned long set_mask_1(int k, int m, int n)
{
    return ~(~0 << m) << n;
}

static unsigned long set_mask_2(int k, int m, int n)
{
    return ((1 << m) - 1) << n;
}

static unsigned long set_mask_3(int k, int m, int n)
{
    return ((~((unsigned long)0) << k) >> (k + n)) << n;
}

static int test_cases[][2] =
{
    { 1, 0 },
    { 1, 1 },
    { 1, 2 },
    { 1, 3 },
    { 2, 1 },
    { 2, 2 },
    { 2, 3 },
    { 3, 4 },
    { 3, 5 },
};

int main(void)
{
    size_t i;
    for (i = 0; i < 9; i++)
    {
        int m = test_cases[i][0];
        int n = test_cases[i][1];
        int k = ULONG_BITS - (m + n);
        printf("%d/%d/%d = 0x%08lX = 0x%08lX = 0x%08lX\n", k, m, n,
               set_mask_1(k, m, n),
               set_mask_2(k, m, n),
               set_mask_3(k, m, n));
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)