Tengo las siguientes definiciones:
#define M(x) ( ((uint64_t) 1) << (x) ) #define Mx M(0) #define My M(1) #define Mz M(2)Muy a menudo necesito reorganizar el orden de Mx, My, Mz, por ejemplo:
#define My M(0) #define Mz M(1) #define Mx M(2) ¿Cómo haría esto más genérico en el sentido de no tener que corregir M(0/1/2) cada vez, sino simplemente barajar las líneas?
#define POS ... #define My M(POS) #define Mz M(POS) #define Mx M(POS)Podría usar una macro adicional en el medio que seleccionará un argumento apropiado de la permutación. La permutación sería una macro en sí misma que puede ser indefinida y redefinida.
#define NTH0(a0,a1,a2) a0 #define NTH1(a0,a1,a2) a1 #define NTH2(a0,a1,a2) a2 #define NTH(n, perm) NTH ## n (perm) #define Mx M(NTH(0, PERM)) #define My M(NTH(1, PERM)) #define Mz M(NTH(2, PERM)) #define PERM 1,2,3 Mx My Mz #undef PERM #define PERM 3,2,1 Mx My Mz Cuando se compila con gcc -E , se expande a:
M(1) M(2) M(3) M(3) M(2) M(1)La mejor solución podría ser resolver esto con control de versiones o interruptores #ifdef en lugar de macros similares a funciones. O tal vez generar la fuente C a través de un script.
De lo contrario, la forma estándar del preprocesador de enumerar cosas y evitar la repetición de código es "X macros", donde solo necesita cambiar los valores en un solo lugar (llamado M_LIST en este ejemplo):
#include <stdio.h> #include <inttypes.h> #define M_LIST(X) \ X(x,0) \ X(y,1) \ X(z,2) \ #define M_enum(symbol,val) M##symbol##_bit = val, enum { M_LIST(M_enum) }; #define M(symbol) ( 1ull << (M##symbol##_bit) ) int main (void) { printf("%.16"PRIx64"\n", M(x)); printf("%.16"PRIx64"\n", M(y)); printf("%.16"PRIx64"\n", M(z)); } Aquí se crea una enumeración temporal, que se expandirá a: enum { Mx_bit = 0, My_bit = 1, Mz_bit = 2, } . Estas constantes no son utilizadas directamente por su programa, sino solo a través de la macro M .