I have the following defines:
#define M(x) ( ((uint64_t) 1) << (x) )
#define Mx M(0)
#define My M(1)
#define Mz M(2)
Quite often I need to rearrange the order of Mx, My, Mz, for example:
#define My M(0)
#define Mz M(1)
#define Mx M(2)
How would I make this more generic in a sense of not having to correct M(0/1/2)
every time, but just shuffle the lines?
#define POS ...
#define My M(POS)
#define Mz M(POS)
#define Mx M(POS)
CodePudding user response:
You could use an extra macro in between that will select an appropriate argument from the permutation. The permutation would be a macro itself that can be undefined and redefined.
#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
When compiled with gcc -E
it expands to:
M(1)
M(2)
M(3)
M(3)
M(2)
M(1)
CodePudding user response:
The best solution might be to solve this with version control or #ifdef
switches rather than function-like macros. Or perhaps generate the C source through a script.
Otherwise, the standard pre-processor way to list stuff while avoiding code repetition is "X macros", where you only need to change the values in a single place (called M_LIST
in this example):
#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));
}
Here a temporary enum is created, which will expand to:
enum { Mx_bit = 0, My_bit = 1, Mz_bit = 2, }
. These constants aren't used directly by your program, but only through the macro M
.