在 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;
}
我想编写一个函数,在调用时将其参数加倍(如果它不为零)或 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;
}