使用宏从给定的一组不同值中查找不等于任何值的值

Pav*_*kin 2 c math macros c-preprocessor

问题:如何实现一个E扩展为整数常量表达式的宏,以便......

(E != (X) && E != (Y) && E != (Z))
Run Code Online (Sandbox Code Playgroud)

X...对于、Y、 和Z作为具有不同非负值的整数常量表达式的每个选择,其计算结果为 1 ?

例子:

#define X               13
#define Y               45
#define Z               76
#define E               FUNC(X,Y,Z)
#define FUNC(X,Y,Z)     ??

E /* evaluates to any number distinct from all of 13, 45, and 76 */
Run Code Online (Sandbox Code Playgroud)

使用哪个公式?有任何想法吗?

chq*_*lie 5

给定任意 3 个数字XYZ,生成一个int与所有 3 个值都不同的常数。

显然0, 、123必须满足标准。所以这里有一个解决方案:

#define FUNC(x,y,z)  (((x) != 0 && (y) != 0 && (z) != 0) ? 0 : \
                      ((x) != 1 && (y) != 1 && (z) != 1) ? 1 : \
                      ((x) != 2 && (y) != 2 && (z) != 2) ? 2 : 3)
Run Code Online (Sandbox Code Playgroud)

这是一个更微妙的解决方案,根据每个参数的最后 2 位计算 、 或 ,但仅计算0参数1一次23

#define FUNC(x,y,z)  ((int)((0x10201030102010 >>           \
                             (4 * ((1 << ((x) & 3)) |      \
                                   (1 << ((y) & 3)) |      \
                                   (1 << ((z) & 3))))) & 3))
Run Code Online (Sandbox Code Playgroud)

解释:

  • 我们组成一个 1 到 14 之间的数字,如果其中一个参数的最后 2 位具有该值,则每个位都会被设置。
  • 将此值乘以4并将幻数移动0x10201030102010相应数量,然后掩码乘以 3 以选择与所有余数不同的值。

可读性较差的版本将乘以2并移位0x484C484,仅使用 32 位算术:

#define FUNC(x,y,z)  ((int)((0x484C484 >> ((2 << ((x) & 3)) | \
                                           (2 << ((y) & 3)) | \
                                           (2 << ((z) & 3)))) & 3))
Run Code Online (Sandbox Code Playgroud)