使用宏从一组给定的不同值中查找不等于任何值的值
Find value unequal to any value from a given set of distinct values using macro
问题:如何实现扩展为整型常量表达式的宏 E
,使得 ...
(E != (X) && E != (Y) && E != (Z))
...对于 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 */
使用哪个公式?有什么想法吗?
Given any 3 numbers X
, Y
and Z
, produce an int
constant that is different from all 3 values.
显然 0
、1
、2
或 3
必须满足条件。所以这是一个解决方案:
#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)
这是一个更微妙的解决方案,根据每个参数的最后 2 位评估 0
、1
、2
或 3
,但评估参数只有一次:
#define FUNC(x,y,z) ((int)((0x10201030102010 >> \
(4 * ((1 << ((x) & 3)) | \
(1 << ((y) & 3)) | \
(1 << ((z) & 3))))) & 3))
解释:
- 我们组成一个介于 1 和 14 之间的数字,如果其中一个参数的最后 2 位具有此值,则设置每个位。
- 将此值乘以
4
并将幻数 0x10201030102010
移动那么多,然后掩码 3 到 select 一个不同于所有余数的值。
可读性较差的版本将乘以 2
并移位 0x484C484
,仅使用 32 位算法:
#define FUNC(x,y,z) ((int)((0x484C484 >> ((2 << ((x) & 3)) | \
(2 << ((y) & 3)) | \
(2 << ((z) & 3)))) & 3))
虽然不像 第一个答案那么直接,但我想补充以下发现:
Only 2 bits of x, y, z
are needed to generate a distinctive value.
如果3个x,y,z
的least-significant-bit都相同,则return x^1
.
否则^ 2
与x,y,z
不同x,y,z
.
#define FUNC2BITS(x,y,z) ( \
(((x)&1 == (y)&1) && ((y)&1 == (z)&1)) ? (x)^1 : \
(((x)&1 == (y)&1) ) ? (z)^2 : \
(((x)&1 == (z)&1) ) ? (y)^2 : (x)^2)
#define FUNC(x,y,z) FUNC2BITS((x)&3, (y)&3, (z)&3)
以上不依赖于 x,y,z
是不同的,也不将它们限制为 non-negative。由于 OP 具有“具有不同的非负值”,因此可以简化为
#define FUNC2BITS(x,y,z) ( \
(((x)&1 == (y)&1) ) ? (z)^2 : \
(((x)&1 == (z)&1) ) ? (y)^2 : (x)^2)
思路:找到当前的max/min和(如果可以的话)add/subtract1
:
#include <limits.h>
#define FUNC(X,Y,Z) \
MAX(X,MAX(Y,Z)) < INT_MAX ? MAX(X,MAX(Y,Z))+1 : \
MIN(X,MIN(Y,Z)) > 0 ? MIN(X,MAX(Y,Z))-1 : \
-1 /* hard case: don't know yet how to implment */
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
int x1 = FUNC(23,45,78); // 79
int x2 = FUNC(0,45,78); // 79
int x3 = FUNC(23,INT_MAX,78); // 22
int x4 = FUNC(0,1,2); // 3
int x5 = FUNC(INT_MAX,34,0); // -1 (hard case)
如果不能add/subtract 1
(例如0, 45, INT_MAX
),则“还不知道”。
问题:如何实现扩展为整型常量表达式的宏 E
,使得 ...
(E != (X) && E != (Y) && E != (Z))
...对于 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 */
使用哪个公式?有什么想法吗?
Given any 3 numbers
X
,Y
andZ
, produce anint
constant that is different from all 3 values.
显然 0
、1
、2
或 3
必须满足条件。所以这是一个解决方案:
#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)
这是一个更微妙的解决方案,根据每个参数的最后 2 位评估 0
、1
、2
或 3
,但评估参数只有一次:
#define FUNC(x,y,z) ((int)((0x10201030102010 >> \
(4 * ((1 << ((x) & 3)) | \
(1 << ((y) & 3)) | \
(1 << ((z) & 3))))) & 3))
解释:
- 我们组成一个介于 1 和 14 之间的数字,如果其中一个参数的最后 2 位具有此值,则设置每个位。
- 将此值乘以
4
并将幻数0x10201030102010
移动那么多,然后掩码 3 到 select 一个不同于所有余数的值。
可读性较差的版本将乘以 2
并移位 0x484C484
,仅使用 32 位算法:
#define FUNC(x,y,z) ((int)((0x484C484 >> ((2 << ((x) & 3)) | \
(2 << ((y) & 3)) | \
(2 << ((z) & 3)))) & 3))
虽然不像
Only 2 bits of
x, y, z
are needed to generate a distinctive value.
如果3个x,y,z
的least-significant-bit都相同,则return x^1
.
否则^ 2
与x,y,z
不同x,y,z
.
#define FUNC2BITS(x,y,z) ( \
(((x)&1 == (y)&1) && ((y)&1 == (z)&1)) ? (x)^1 : \
(((x)&1 == (y)&1) ) ? (z)^2 : \
(((x)&1 == (z)&1) ) ? (y)^2 : (x)^2)
#define FUNC(x,y,z) FUNC2BITS((x)&3, (y)&3, (z)&3)
以上不依赖于 x,y,z
是不同的,也不将它们限制为 non-negative。由于 OP 具有“具有不同的非负值”,因此可以简化为
#define FUNC2BITS(x,y,z) ( \
(((x)&1 == (y)&1) ) ? (z)^2 : \
(((x)&1 == (z)&1) ) ? (y)^2 : (x)^2)
思路:找到当前的max/min和(如果可以的话)add/subtract1
:
#include <limits.h>
#define FUNC(X,Y,Z) \
MAX(X,MAX(Y,Z)) < INT_MAX ? MAX(X,MAX(Y,Z))+1 : \
MIN(X,MIN(Y,Z)) > 0 ? MIN(X,MAX(Y,Z))-1 : \
-1 /* hard case: don't know yet how to implment */
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
int x1 = FUNC(23,45,78); // 79
int x2 = FUNC(0,45,78); // 79
int x3 = FUNC(23,INT_MAX,78); // 22
int x4 = FUNC(0,1,2); // 3
int x5 = FUNC(INT_MAX,34,0); // -1 (hard case)
如果不能add/subtract 1
(例如0, 45, INT_MAX
),则“还不知道”。