Pregunta: cómo implementar una macro E que se expande a una expresión constante entera tal que...
(E != (X) && E != (Y) && E != (Z)) ... se evalúa como 1 para cada elección de X , Y y Z como expresiones constantes enteras con valores distintos no negativos?
Ejemplo:
#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 */¿Qué fórmula usar? ¿Algunas ideas?
Dados 3 números
X,YyZ, produzca una constanteintque sea diferente de los 3 valores.
Parece obvio que 0 , 1 , 2 o 3 deben cumplir los criterios. Así que aquí hay una solución:
#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) Aquí hay una solución más sutil que evalúa a 0 , 1 , 2 o 3 dependiendo de los últimos 2 bits de cada uno de los argumentos, pero evalúa los argumentos solo una vez:
#define FUNC(x,y,z) ((int)((0x10201030102010 >> \ (4 * ((1 << ((x) & 3)) | \ (1 << ((y) & 3)) | \ (1 << ((z) & 3))))) & 3))Explicación:
4 y cambie el número mágico 0x10201030102010 por esa cantidad y enmascare por 3 para seleccionar un valor que sea diferente de todos los residuos. Una versión menos legible multiplicaría por 2 y cambiaría 0x484C484 , usando solo aritmética de 32 bits:
#define FUNC(x,y,z) ((int)((0x484C484 >> ((2 << ((x) & 3)) | \ (2 << ((y) & 3)) | \ (2 << ((z) & 3)))) & 3))Aunque no es tan directo como la primera respuesta de @chqrlie , quería agregar el siguiente hallazgo:
Solo se necesitan 2 bits de
x, y, zpara generar un valor distintivo.
Si el bit menos significativo de los 3 x,y,z es el mismo, devuelve x^1 .
De lo contrario ^ 2 con los diferentes 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) Lo anterior no se basa en que x,y,z sean distintos ni los restringe a no negativos. Como OP tiene "con valores distintos, no negativos", puede simplificar a
#define FUNC2BITS(x,y,z) ( \ (((x)&1 == (y)&1) ) ? (z)^2 : \ (((x)&1 == (z)&1) ) ? (y)^2 : (x)^2)Idea: encuentre el máximo/mínimo actual y (si puede) sume/reste 1 :
#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) Si no puede sumar/restar 1 (por ejemplo 0, 45, INT_MAX ), entonces "todavía no lo sé".