Topic for today - C Macros with multiple arguments!

While I know I can always make multiple macros, but just having the one macro that supports multiple arguments would of course be nice! A little bit of research plus a lot of thinking and I discovered that by starting with the multiple macros, you can add 2 extra macros and end up with a final macro that is the only one you need to use as it supports multiple arguments!

// The multiple macros that you would need anyway
#define XXX_0() <code for no arguments>
#define XXX_1(A) <code for one argument>
#define XXX_2(A,B) <code for two arguments>
#define XXX_3(A,B,C) <code for three arguments>
#define XXX_4(A,B,C,D) <code for four arguments>

// The additional macro simply keeps the 6th argument which is always what we want
#define XXX_X(x,A,B,C,D,FUNC, ...) FUNC

// The final macro - the one that the programmer uses
#define XXX(...) XXX_X(,##__VA_ARGS__,\
XXX_4(__VA_ARGS__),\
XXX_3(__VA_ARGS__),\
XXX_2(__VA_ARGS__),\
XXX_1(__VA_ARGS__),\
XXX_0(__VA_ARGS__)\
)

Now that I understand it, it's time to share the method and explain/record how it actually works, starting with the following code...

XXX();
XXX(1);
XXX(1,2);
XXX(1,2,3);
XXX(1,2,3,4);
XXX(1,2,3,4,5); // Not actually valid, but included to show the process

Becomes...

XXX_X(, XXX_4(), XXX_3(), XXX_2(), XXX_1(), XXX_0() );
XXX_X(,1, XXX_4(1), XXX_3(1), XXX_2(1), XXX_1(1), XXX_0(1) );
XXX_X(,1,2, XXX_4(1,2), XXX_3(1,2), XXX_2(1,2), XXX_1(1,2), XXX_0(1,2) );
XXX_X(,1,2,3, XXX_4(1,2,3), XXX_3(1,2,3), XXX_2(1,2,3), XXX_1(1,2,3), XXX_0(1,2,3) );
XXX_X(,1,2,3,4, XXX_4(1,2,3,4), XXX_3(1,2,3,4), XXX_2(1,2,3,4), XXX_1(1,2,3,4), XXX_0(1,2,3,4) );
XXX_X(,1,2,3,4,5, XXX_4(1,2,3,4,5), XXX_3(1,2,3,4,5), XXX_2(1,2,3,4,5), XXX_1(1,2,3,4,5), XXX_0(1,2,3,4,5) );

Which becomes...

XXX_0();
XXX_1(1);
XXX_2(1,2);
XXX_3(1,2,3);
XXX_4(1,2,3,4);
5;

So, we see that for the valid entries, even though the user entered "XXX(...)" they got the same result as if they had used the multiple macros method!

Note: Remove the #define for XXX_0 to get a compile error [ie: if a no argument option it is not allowed].