在 C 中没有分支的双倍或设置整数

Double or set integer without branching in C

我想编写一个函数,在调用时将其参数加倍(如果它不为零)或 returns 一个特定常量(如果它为零)。如果有帮助,常数总是 2 的幂。

假设常量是 8。当用 0 调用时,我希望它为 return 8。当用 8 调用时,我希望它为 return 16。依此类推。

简单的方法是这样的:

unsigned foo(unsigned value)
{
    return (value ? value * 2 : 8);
}

是否可以在不分支的情况下执行此操作?

static int myconst[2] = { 8, 0 };
int f(int x)
{
    return x + x + myconst[!!x];
}

主要使用位运算符:

int foo(int n)
{
     const int d = 8;            // default return value for n == 0
     int mask = (n == 0) - 1;    // generate mask = 0 if n == 0, otherwise all 1s
     return ((n << 1) & mask) | (d & ~mask);
}

我们来测试一下:

#include <stdio.h>

static int foo(int n)
{
     const int d = 8;            // default return value for n == 0
     int mask = (n == 0) - 1;    // generate mask = 0 if n == 0, otherwise all 1s
     return ((n << 1) & mask) | (d & ~mask);
}

int main()
{
    const int tests[] = { 8, 1, 0, -1, -8 };

    for (int i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
    {
        printf("%4d -> %4d\n", tests[i], foo(tests[i]));
    }
    return 0;
}

编译并运行:

$ gcc -Wall double_fun.c && ./a.out
   8 ->   16
   1 ->    2
   0 ->    8
  -1 ->   -2
  -8 ->  -16

这不会导致额外的内存访问。

int f(int a)
{
    const int c = 8;
    return (a*2)+(a==0)*c;
}