Adding separators in iteration over __VA_ARGS__ in C/C++ macro - c

background
I'm trying to make automatic generator of Lua-C interface using C macros. The biggest problem was to make it general for varying number of arguments, which I resolved by using __VA_ARGS__ with help of this answer: Is it possible to iterate over arguments in variadic macros?
Simpler almost working solution
this solution almost works, but it produce some redudant commas (nottice ,,,, in output)
// helper macros for iteration over __VA_ARGS__
#define ARG1(WHAT,X,...) WHAT(X)ARG2(WHAT,__VA_ARGS__)
#define ARG2(WHAT,X,...) WHAT(X)ARG3(WHAT,__VA_ARGS__)
#define ARG3(WHAT,X,...) WHAT(X)ARG4(WHAT,__VA_ARGS__)
#define ARG4(WHAT,X,...) WHAT(X)ARG5(WHAT,__VA_ARGS__)
#define ARG5(WHAT,X,...) WHAT(X)ARG6(WHAT,__VA_ARGS__)
#define ARG6(WHAT,X,...) WHAT(X)//ARG2(__VA_ARGS__)
// macros dispatch propper type of Lua::get
#define LUA_GET_int(i) Lua::getInt(L,i)
#define LUA_GET_long(i) Lua::getInt(L,i)
#define LUA_GET_float(i) (float)Lua::getDouble(L,i)
#define LUA_GET_double(i) Lua::getDouble(L,i)
#define LUA_GET_string(i) Lua::getString(L,i)
#define LUA_PUSH_int(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushnumber(L,a)
#define LUA_PUSH_double(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushstring(L,a)
#define LUA_GET_(T)
#define LUA_GET(T) ,LUA_GET_##T(i++) // commas come from here
#define MAKE_LUA_FUNC(TR,fname,T1,...) int l_##fname(lua_State * L){ int i=0; LUA_PUSH_##TR( fname( LUA_GET_##T1(i++) ARG1(LUA_GET,__VA_ARGS__) ) ); return 1; }
// interface for function:
// double add3(float, int, double );
MAKE_LUA_FUNC( double, add3, float, int, double )
// output:
// 'int l_add3(lua_State * L){ int i=0; lua_pushnumber(L,add3((float)Lua::getDouble(L,i++) ,Lua::getInt(L,i++),Lua::getDouble(L,i++),,,, )); return 1; }'
Working but less-nice solution
I had to duplicate LUA_GET_ macros for case when it is first in argument list (without comma) and otherwise (with comma in front)
// begin of argument list => no commas
#define LUA_GET_int(i) Lua::getInt(L,i)
#define LUA_GET_long(i) Lua::getInt(L,i)
#define LUA_GET_float(i) (float)Lua::getDouble(L,i)
#define LUA_GET_double(i) Lua::getDouble(L,i)
#define LUA_GET_string(i) Lua::getString(L,i)
// rest of argument list => with commas
#define LUA_GET__int(i) ,Lua::getInt(L,i)
#define LUA_GET__long(i) ,Lua::getInt(L,i)
#define LUA_GET__float(i) ,(float)Lua::getDouble(L,i)
#define LUA_GET__double(i) ,Lua::getDouble(L,i)
#define LUA_GET__string(i) ,Lua::getString(L,i)
#define LUA_PUSH_int(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushnumber(L,a)
#define LUA_PUSH_double(a) lua_pushnumber(L,a)
#define LUA_PUSH_float(a) lua_pushstring(L,a)
#define LUA_GET_(T)
#define LUA_GET__(T)
#define LUA_GET(T) LUA_GET__##T(i++)
#define MAKE_LUA_FUNC(TR,fname,T1,...) int l_##fname(lua_State * L){ int i=0; LUA_PUSH_##TR( fname( LUA_GET_##T1(i++) ARG1(LUA_GET,__VA_ARGS__) ) ); return 1; }
// MAKE_LUA_FUNC( double, add3, float, int, double )
// output:
// int l_add3(lua_State * L){ int i=0; lua_pushnumber(L,add3( (float)Lua::getDouble(L,i++) ,Lua::getInt(L,i++),Lua::getDouble(L,i++) )); return 1; }
Is it possible to make it simpler / nicer ?
NOTE - for debugging I found very useful this Seeing expanded C macros in particular https://stackoverflow.com/a/31460434/1291544

You need to count the number of arguments you have, and then call the corresponding ARG# macro.
#define ARGS_N(M,...) \
ARGS_N__(__VA_ARGS__, 6, 5, 4, 3, 2, 1)(M, __VA_ARGS__)
#define ARGS_N__(_1, _2, _3, _4, _5, _6, X, ...) ARGS_##X
#define ARGS_1(M, X) M(X)
#define ARGS_2(M, X, ...) M(X)ARGS_1(M, __VA_ARGS__)
#define ARGS_3(M, X, ...) M(X)ARGS_2(M, __VA_ARGS__)
#define ARGS_4(M, X, ...) M(X)ARGS_3(M, __VA_ARGS__)
#define ARGS_5(M, X, ...) M(X)ARGS_4(M, __VA_ARGS__)
#define ARGS_6(M, X, ...) M(X)ARGS_5(M, __VA_ARGS__)
Now, change MAKE_LUA_FUNC to call ARGS_N instead of your ARG1.
The way the counting technique works is that ARGS_N invokes the helper ARGS_N__ with the variable arguments, and then pads out the invocation with additional arguments. ARGS_N__ does the counting by always utilizing the 7th argument. So, if ARGS_N is provided 4 variable arguments after the first one, ARGS_N__ will produce ARGS_4, because in that case, in the padding provided by ARGS_N, 4 would be the 7th argument.
ARGS_N__(__VA_ARGS__, 6, 5, 4, 3, 2, 1)(M, __VA_ARGS__)
. .
/|\ /|\
| |
If this has 4 arguments
|
This would be the 7th argument
This is the same technique that was shown in the answer you pointed to. However, that version was a bit more complicated than the version I am illustrating for you, so hopefully you will find this explanation helpful.

Related

How to map #define's replacement list containing space(s) to integers (IDs)?

A #define's replacement list containing no spaces can be mapped to integers (IDs):
#define ID_double 1
#define ID_float 2
#define ID_long_double 3
#define ID_(x) ID_##x
#define ID(x) ID_(x)
#define T double
T v;
int x = ID(T); /* 1 */
Now consider:
#define T long double
The code above won't compile:
<source>:3:25: error: 'ID_long' undeclared here (not in a function)
Question: is there a way to support spaces?
For example (somehow):
#define REPLACE_SPACES_TO_UNDERSCORES(x) ??
#define ID(x) ID_(REPLACE_SPACES_TO_UNDERSCORES(x))
#define T long double
T v;
int x = ID(T); /* 3 */
The same idea I had in Replace spaces with underscores in a macro? can also be used here, and the dictionary will be much more realistical in size. In the following code on the end, ID(T) is replaced by 3.
// dictionary
#define WORD_long long,
#define WORD_double double,
// ---------------------------------------------
// the classics
#define COMMA(...) ,
#define FIRST(a, ...) a
// apply function f for each argument recursively with tail
#define FOREACHTAIL_1(f,a) f(a,)
#define FOREACHTAIL_2(f,a,...) f(a,FOREACHTAIL_1(f,__VA_ARGS__))
#define FOREACHTAIL_3(f,a,...) f(a,FOREACHTAIL_2(f,__VA_ARGS__))
#define FOREACHTAIL_4(f,a,...) f(a,FOREACHTAIL_3(f,__VA_ARGS__))
#define FOREACHTAIL_N(_4,_3,_2,_1,N,...) \
FOREACHTAIL_##N
#define FOREACHTAIL(f,...) \
FOREACHTAIL_N(__VA_ARGS__,4,3,2,1)(f,__VA_ARGS__)
// if there are two arguments, expand to true. Otherwise false.
#define IFTWO_N(_0,_1,N,...) N
#define IFTWO(true, false, ...) IFTWO_N(__VA_ARGS__, true, false)
// If empty, expand to true, otherwise false.
// https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
#define IFEMPTY(true, false, ...) IFTWO(true, false, COMMA __VA_ARGS__ ())
// Join arguments with `_`.
#define JOIN_U(a, b) a##_##b
#define JOIN_TWO_IN(a,b) IFEMPTY(FIRST, JOIN_U, b)(a, b)
#define JOIN_TWO(a,b) JOIN_TWO_IN(a,b)
#define JOIN(...) FOREACHTAIL(JOIN_TWO, __VA_ARGS__)
// Append WORD_ to each argument and join arguments with spaces.
#define WORD_ /* the last one expands to empty */
#define WORDS_TWO(a, b) WORD_##a b
#define WORDS(...) FOREACHTAIL(WORDS_TWO, __VA_ARGS__)
#define REPLACE_SPACES_TO_UNDERSCORES(a) JOIN(WORDS(WORDS(WORDS(WORDS(WORDS(a))))))
// --------------------------------------------
#define ID_double 1
#define ID_float 2
#define ID_long_double 3
#define ID_IN2(x) ID_##x
#define ID_IN(x) ID_IN2(x)
#define ID(x) ID_IN(REPLACE_SPACES_TO_UNDERSCORES(x))
int main() {
#define T long double
T v;
int x = ID(T); /* 3 */
}

#ifdef inside a #define?

I'm initializing an array of structures with the help of a define like this:
#define FLAGCODE(name) { #name, MNT_ ## name }
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS),
FLAGCODE(ASYNC),
...
This works nicely, and now I'd like to add a check, whether each flag (such as MNT_ACLS) is defined without inserting an #ifdef and #endif for each symbol by hand?
That is, I want the macro FLAGCODE(name) to expand into (an equivalent of):
#ifdef MNT_ ##name
{ # name, MNT_ ##name },
#endif
Exempli gratia, if name is NOATIME, the code shall become:
#ifdef MNT_NOATIME
{ "NOATIME", MNT_NOATIME },
#endif
Yes, I realize, that this would mean double pass through preprocessor, and so is unlikely to be possible -- without a custom code-generator... But still...
There is a solution but highly not recommended! You could do funny things with C-preprocessor (cf. Macro to replace nested for loops and links in the question). But I repeat it: Don't do it. It is a cpp abuse.
In two words, you have to create your own #ifdef with macro. In the code below, ISDEF is an "operator" to check if the flag is defined and #if has been redefined: IIF (To understand, all explanations are here: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define COMMA ,
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define PROBE(x) x, 1,
#define ISDEF(x) CHECK(PRIMITIVE_CAT(ISDEF_, x))
#define ISDEF_ PROBE(~)
#define FLAGCODE(name) IIF(ISDEF(name))({ #name COMMA MNT_ ## name }COMMA)
#define ACLS
#define FLAGDEFINED
int main()
{
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS)
FLAGCODE(ASYNC)
FLAGCODE(FLAGDEFINED)
FLAGCODE(FLAGNOTDEFINED)
...
You could also do a list with your flags (cf. MAP part in http://jhnet.co.uk/articles/cpp_magic).
Enjoy but do not go overboard with preprocessor.
Following the very good comment of Chris Dodd,
1 : This tricks works if the flag is define as empty (#define FLAGDEFINED). It does not work with, for example, #define FLAGDEFINED 1 or #define FLAGDEFINED xxx.
2 : CPP_ prefix has been added and name is changed by CPP_FLAG
#define CPP_PRIMITIVE_CAT(CPP_a, ...) CPP_a ## __VA_ARGS__
#define CPP_COMMA ,
#define CPP_IIF(CPP_c) CPP_PRIMITIVE_CAT(CPP_IIF_, CPP_c)
#define CPP_IIF_0(CPP_t, ...) __VA_ARGS__
#define CPP_IIF_1(CPP_t, ...) CPP_t
#define CPP_CHECK_N(CPP_x, CPP_n, ...) CPP_n
#define CPP_CHECK(...) CPP_CHECK_N(__VA_ARGS__, 0,)
#define CPP_PROBE(CPP_x) CPP_x, 1,
#define CPP_ISDEF(CPP_x) CPP_CHECK(CPP_PRIMITIVE_CAT(CPP_ISDEF_, CPP_x))
#define CPP_ISDEF_ CPP_PROBE(~)
#define CPP_FLAGCODE(CPP_FLAG) CPP_IIF(CPP_ISDEF(CPP_FLAG))({ #CPP_FLAG CPP_COMMA MNT_ ## CPP_FLAG }CPP_COMMA)
#define ACLS
#define FLAGDEFINED

C Macros: How to map another macro to variadic arguments?

I'd like to know how to apply a unary function (or another macro) to variadic arguments of a macro, like
int f(int a);
#define apply(args...) <the magic>
apply(a, b, c)
which unrolls
f(a)
f(b)
f(c)
Note that the number of arguments is unknown.
The code below is working for what you've asked for with up to 1024 arguments and without using additional stuff like boost. It defines an EVAL(...) and also a MAP(m, first, ...) macro to do recursion and to use for each iteration the macro m with the next parameter first.
With the use of that, your apply(...) looks like: #define apply(...) EVAL(MAP(apply_, __VA_ARGS__)).
It is mostly copied from C Pre-Processor Magic. It is also great explained there. You can also download these helper macros like EVAL(...) at this git repository, there are also a lot of explanation in the actual code. It is variadic so it takes the number of arguments you want.
But I changed the FIRST and the SECOND macro as it uses a Gnu extension like it is in the source I've copied it from. This is said in the comments below by #HWalters:
Specifically, 6.10.3p4: "Otherwise [the identifier-list ends in a ...] there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...)".
Main function part:
int main()
{
int a, b, c;
apply(a, b, c) /* Expands to: f(a); f(b); f(c); */
return 0;
}
Macro definitions:
#define FIRST_(a, ...) a
#define SECOND_(a, b, ...) b
#define FIRST(...) FIRST_(__VA_ARGS__,)
#define SECOND(...) SECOND_(__VA_ARGS__,)
#define EMPTY()
#define EVAL(...) EVAL1024(__VA_ARGS__)
#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
#define EVAL1(...) __VA_ARGS__
#define DEFER1(m) m EMPTY()
#define DEFER2(m) m EMPTY EMPTY()()
#define IS_PROBE(...) SECOND(__VA_ARGS__, 0)
#define PROBE() ~, 1
#define CAT(a,b) a ## b
#define NOT(x) IS_PROBE(CAT(_NOT_, x))
#define _NOT_0 PROBE()
#define BOOL(x) NOT(NOT(x))
#define IF_ELSE(condition) _IF_ELSE(BOOL(condition))
#define _IF_ELSE(condition) CAT(_IF_, condition)
#define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
#define _IF_0(...) _IF_0_ELSE
#define _IF_1_ELSE(...)
#define _IF_0_ELSE(...) __VA_ARGS__
#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
#define _END_OF_ARGUMENTS_() 0
#define MAP(m, first, ...) \
m(first) \
IF_ELSE(HAS_ARGS(__VA_ARGS__))( \
DEFER2(_MAP)()(m, __VA_ARGS__) \
)( \
/* Do nothing, just terminate */ \
)
#define _MAP() MAP
#define apply_(x) f(x);
#define apply(...) EVAL(MAP(apply_, __VA_ARGS__))
To test macro expansion it is useful to use gcc with the command line argument -E:
$ gcc -E srcFile.c
because your're getting concrete error messages and understand what's going on.
Everything is possible in C if you throw enough ugly macros at it. For example, you can have an ugly function-like macro:
#include <stdio.h>
int f (int a)
{
printf("%d\n", a);
}
#define SIZEOF(arr) (sizeof(arr) / sizeof(*arr))
#define apply(...) \
{ \
int arr[] = {__VA_ARGS__}; \
for(size_t i=0; i<SIZEOF(arr); i++) \
{ \
f(arr[i]); \
} \
}
int main (void)
{
apply(1, 2, 3);
}
Notice that 1) This would be much better off as a variadic function, and 2) it would be even better if you get rid of the variadic nonsense entirely and simply make a function such as
int f (size_t n, int array[n])

Use an optional argument in a macro in C [duplicate]

Is there some way of getting optional parameters with C++ Macros? Some sort of overloading would be nice too.
Here's one way to do it. It uses the list of arguments twice, first to form the name of the helper macro, and then to pass the arguments to that helper macro. It uses a standard trick to count the number of arguments to a macro.
enum
{
plain = 0,
bold = 1,
italic = 2
};
void PrintString(const char* message, int size, int style)
{
}
#define PRINT_STRING_1_ARGS(message) PrintString(message, 0, 0)
#define PRINT_STRING_2_ARGS(message, size) PrintString(message, size, 0)
#define PRINT_STRING_3_ARGS(message, size, style) PrintString(message, size, style)
#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
#define PRINT_STRING_MACRO_CHOOSER(...) \
GET_4TH_ARG(__VA_ARGS__, PRINT_STRING_3_ARGS, \
PRINT_STRING_2_ARGS, PRINT_STRING_1_ARGS, )
#define PRINT_STRING(...) PRINT_STRING_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
int main(int argc, char * const argv[])
{
PRINT_STRING("Hello, World!");
PRINT_STRING("Hello, World!", 18);
PRINT_STRING("Hello, World!", 18, bold);
return 0;
}
This makes it easier for the caller of the macro, but not the writer.
With great respect to Derek Ledbetter for his answer — and with apologies for reviving an old question.
Getting an understanding of what it was doing and picking up elsewhere on the ability to preceed the __VA_ARGS__ with ## allowed me to come up with a variation...
// The multiple macros that you would need anyway [as per: Crazy Eddie]
#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 interim macro that simply strips the excess and ends up with the required macro
#define XXX_X(x,A,B,C,D,FUNC, ...) FUNC
// The macro 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__)\
)
For non-experts like me who stumble upon the answer, but can't quite see how it works, I'll step through the actual processing, 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 just the sixth argument...
XXX_0();
XXX_1(1);
XXX_2(1,2);
XXX_3(1,2,3);
XXX_4(1,2,3,4);
5;
PS: Remove the #define for XXX_0 to get a compile error [ie: if a no-argument option is not allowed].
PPS: Would be nice to have the invalid situations (eg: 5) be something that gives a clearer compilation error to the programmer!
PPPS: I'm not an expert, so I'm very happy to hear comments (good, bad or other)!
With greatest respect to Derek Ledbetter, David Sorkovsky, Syphorlate for their answers, together with the ingenious method to detect empty macro arguments by Jens Gustedt at
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
finally I come out with something that incorporates all the tricks, so that the solution
Uses only standard C99 macros to achieve function overloading, no GCC/CLANG/MSVC extension involved (i.e., comma swallowing by the specific expression , ##__VA_ARGS__ for GCC/CLANG, and implicit swallowing by ##__VA_ARGS__ for MSVC). So feel free to pass the missing --std=c99 to your compiler if you wish =)
Works for zero argument, as well as unlimited number of arguments, if you expand it further to suit your needs
Works reasonably cross-platform, at least tested for
GNU/Linux + GCC (GCC 4.9.2 on CentOS 7.0 x86_64)
GNU/Linux + CLANG/LLVM, (CLANG/LLVM 3.5.0 on CentOS 7.0 x86_64)
OS X + Xcode, (XCode 6.1.1 on OS X Yosemite 10.10.1)
Windows + Visual Studio, (Visual Studio 2013 Update 4 on Windows 7 SP1 64 bits)
For the lazies, just skip to the very last of this post to copy the source. Below is the detailed explanation, which hopefully helps and inspires all people looking for the general __VA_ARGS__ solutions like me. =)
Here's how it goes. First define the user-visible overloaded "function", I named it create, and the related actual function definition realCreate, and the macro definitions with different number of arguments CREATE_2, CREATE_1, CREATE_0, as shown below:
#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
void realCreate(int x, int y)
{
printf("(%d, %d)\n", x, y);
}
#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)
The MACRO_CHOOSER(__VA_ARGS__) part ultimately resolves to the macro definition names, and the second (__VA_ARGS__) part comprises their parameter lists. So a user's call to create(10) resolves to CREATE_1(10), the CREATE_1 part comes from MACRO_CHOOSER(__VA_ARGS__), and the (10) part comes from the second (__VA_ARGS__).
The MACRO_CHOOSER uses the trick that, if __VA_ARGS__ is empty, the following expression is concatenated into a valid macro call by the preprocessor:
NO_ARG_EXPANDER __VA_ARGS__ () // simply shrinks to NO_ARG_EXPANDER()
Ingeniusly, we can define this resulting macro call as
#define NO_ARG_EXPANDER() ,,CREATE_0
Note the two commas, they are explained soon. The next useful macro is
#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())
so the calls of
create();
create(10);
create(20, 20);
are actually expanded to
CHOOSE_FROM_ARG_COUNT(,,CREATE_0)();
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 10 ())(10);
CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER 20, 20 ())(20, 20);
As the macro name suggests, we are to count number of arguments later. Here comes another trick: the preprocessor only does simple text replacement. It infers the number of arguments of a macro call merely from the number of commas it sees inside the parentheses. The actual "arguments" separated by commas need not to be of valid syntax. They can be any text. That's to say, in the above example, NO_ARG_EXPANDER 10 () is counted as 1 argument for the middle call. NO_ARG_EXPANDER 20 and 20 () are counted as 2 arguments for the bottom call respectively.
If we use the following helper macros to further expand them
##define CHOOSE_FROM_ARG_COUNT(...) \
FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define FUNC_RECOMPOSER(argsWithParentheses) \
FUNC_CHOOSER argsWithParentheses
The trailing , after CREATE_1 is a work-around for GCC/CLANG, suppressing a (false positive) error saying that ISO C99 requires rest arguments to be used when passing -pedantic to your compiler. The FUNC_RECOMPOSER is a work-around for MSVC, or it can not count number of arguments (i.e., commas) inside the parentheses of macro calls correctly. The results are further resolved to
FUNC_CHOOSER (,,CREATE_0, CREATE_2, CREATE_1, )();
FUNC_CHOOSER (NO_ARG_EXPANDER 10 (), CREATE_2, CREATE_1, )(10);
FUNC_CHOOSER (NO_ARG_EXPANDER 20, 20 (), CREATE_2, CREATE_1, )(20, 20);
As the eagle-eyed you may have seen, the last only step we need is to employ a standard argument counting trick to finally pick the wanted macro version names:
#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
which resolves the results to
CREATE_0();
CREATE_1(10);
CREATE_2(20, 20);
and certainly gives us the desired, actual function calls:
realCreate(0, 0);
realCreate(10, 10);
realCreate(20, 20);
Putting all together, with some rearrangement of statements for better readability, the whole source of the 2-argument example is here:
#include <stdio.h>
void realCreate(int x, int y)
{
printf("(%d, %d)\n", x, y);
}
#define CREATE_2(x, y) realCreate(x, y)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_0() CREATE_1(0)
#define FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(...) FUNC_RECOMPOSER((__VA_ARGS__, CREATE_2, CREATE_1, ))
#define NO_ARG_EXPANDER() ,,CREATE_0
#define MACRO_CHOOSER(...) CHOOSE_FROM_ARG_COUNT(NO_ARG_EXPANDER __VA_ARGS__ ())
#define create(...) MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
int main()
{
create();
create(10);
create(20, 20);
//create(30, 30, 30); // Compilation error
return 0;
}
Although complicated, ugly, burdening the API developer, there comes a solution for overloading and setting optional parameters of C/C++ functions to us crazy people. The usage of the out-coming overloaded APIs become very enjoyable and pleasant. =)
If there is any further possible simplification of this approach, please do let me know at
https://github.com/jason-deng/C99FunctionOverload
Again special thanks to all of the brilliant people that inspired and led me to achieve this piece of work! =)
C++ macros haven't changed from C. Since C didn't have overloading and default arguments for functions, it certainly didn't have them for macros. So to answer your question: no, those features don't exist for macros. Your only option is to define multiple macros with different names (or not use macros at all).
As a sidenote: In C++ it's generally considered good practice to move away from macros as much as possible. If you need features like this, there's a good chance you're overusing macros.
For anyone painfully searching some VA_NARGS solution that works with Visual C++. Following macro worked for me flawlessly(also with zero parameters!) in visual c++ express 2010:
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N,...) N
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS(...) bool(#__VA_ARGS__) ? (VA_NUM_ARGS_IMPL_((__VA_ARGS__, 24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))) : 0
If you want a macro with optional parameters you can do:
//macro selection(vc++)
#define SELMACRO_IMPL(_1,_2,_3, N,...) N
#define SELMACRO_IMPL_(tuple) SELMACRO_IMPL tuple
#define mymacro1(var1) var1
#define mymacro2(var1,var2) var2*var1
#define mymacro3(var1,var2,var3) var1*var2*var3
#define mymacro(...) SELMACRO_IMPL_((__VA_ARGS__, mymacro3(__VA_ARGS__), mymacro2(__VA_ARGS__), mymacro1(__VA_ARGS__)))
That worked for me aswell in vc. But it doesn't work for zero parameters.
int x=99;
x=mymacro(2);//2
x=mymacro(2,2);//4
x=mymacro(2,2,2);//8
gcc/g++ supports varargs macros but I don't think this is standard, so use it at your own risk.
More concise version of Derek Ledbetter's code:
enum
{
plain = 0,
bold = 1,
italic = 2
};
void PrintString(const char* message = NULL, int size = 0, int style = 0)
{
}
#define PRINT_STRING(...) PrintString(__VA_ARGS__)
int main(int argc, char * const argv[])
{
PRINT_STRING("Hello, World!");
PRINT_STRING("Hello, World!", 18);
PRINT_STRING("Hello, World!", 18, bold);
return 0;
}
#include <stdio.h>
#define PP_NARG(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define PP_CONCAT(a,b) PP_CONCAT_(a,b)
#define PP_CONCAT_(a,b) a ## b
#define THINK(...) PP_CONCAT(THINK_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)
#define THINK_0() THINK_1("sector zz9 plural z alpha")
#define THINK_1(location) THINK_2(location, 42)
#define THINK_2(location,answer) THINK_3(location, answer, "deep thought")
#define THINK_3(location,answer,computer) \
printf ("The answer is %d. This was calculated by %s, and a computer to figure out what this"
" actually means will be build in %s\n", (answer), (computer), (location))
int
main (int argc, char *argv[])
{
THINK (); /* On compilers other than GCC you have to call with least one non-default argument */
}
DISCLAIMER: Mostly harmless.
As a big fan of horrible macro monsters, I wanted to expand on Jason Deng's answer and make it actually usable. (For better or worse.) The original is not very nice to use because you need to modify the big alphabet soup every time you want to make a new macro and it's even worse if you need different amount of arguments.
So I made a version with these features:
0 argument case works
1 to 16 arguments without any modifications to the messy part
Easy to write more macro functions
Tested in gcc 10, clang 9, Visual Studio 2017
Currently I just made 16 argument maximum, but if you need more (really now? you're just getting silly...) you can edit FUNC_CHOOSER and CHOOSE_FROM_ARG_COUNT, then add some commas to NO_ARG_EXPANDER.
Please see Jason Deng's excellent answer for more details on the implementation, but I'll just put the code here:
#include <stdio.h>
void realCreate(int x, int y)
{
printf("(%d, %d)\n", x, y);
}
// This part you put in some library header:
#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16, ...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F, ...) FUNC_RECOMPOSER((__VA_ARGS__, \
F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))
#define NO_ARG_EXPANDER(FUNC) ,,,,,,,,,,,,,,,,FUNC ## _0
#define MACRO_CHOOSER(FUNC, ...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))
#define MULTI_MACRO(FUNC, ...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)
// When you need to make a macro with default arguments, use this:
#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)
#define CREATE_0() CREATE_1(0)
#define CREATE_1(x) CREATE_2(x, 0)
#define CREATE_2(x, y) \
do { \
/* put whatever code you want in the last macro */ \
realCreate(x, y); \
} while(0)
int main()
{
create();
create(10);
create(20, 20);
//create(30, 30, 30); // Compilation error
return 0;
}
That's not really what the preprocessor is designed for.
That said, if you want to enter into the area of seriously challenging macro programming with a modicum of readability, you should take a look at the Boost preprocessor library. After all, it wouldn't be C++ if there weren't three completely Turing compatible levels of programming (preprocessor, template metaprogramming, and base level C++)!
#define MY_MACRO_3(X,Y,Z) ...
#define MY_MACRO_2(X,Y) MY_MACRO(X,Y,5)
#define MY_MACRO_1(X) MY_MACRO(X,42,5)
You know at the point of call how many args you're going to pass in so there's really no need for overloading.
You can use BOOST_PP_OVERLOAD from a boost library.
Example from official boost doc:
#include <boost/preprocessor/facilities/overload.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#define MACRO_1(number) MACRO_2(number,10)
#define MACRO_2(number1,number2) BOOST_PP_ADD(number1,number2)
#if !BOOST_PP_VARIADICS_MSVC
#define MACRO_ADD_NUMBERS(...) BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__)
#else
// or for Visual C++
#define MACRO_ADD_NUMBERS(...) \
BOOST_PP_CAT(BOOST_PP_OVERLOAD(MACRO_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY())
#endif
MACRO_ADD_NUMBERS(5) // output is 15
MACRO_ADD_NUMBERS(3,6) // output is 9
Depending on what you need, you could do it with var args with macros. Now, optional parameters or macro overloading, there is no such thing.
Not directly answering the question, but using the same trick as David Sorkovsky answer and giving a clear example of how to build complex macros.
Just compile this with g++ -E test.cpp -o test && cat test:
// #define GET_FIRST_ARG_0_ARGS(default) (default)
// #define GET_FIRST_ARG_1_ARGS(default, a) (a)
// #define GET_FIRST_ARG_2_ARGS(default, a, b) (a)
// #define GET_FIRST_ARG_3_ARGS(default, a, b, c) (a)
// #define GET_FIRST_ARG_4_ARGS(default, a, b, c, d) (a)
#define GET_FIRST_ARG_MACROS(default, a, b, c, d, macro, ...) macro
#define GET_FIRST_ARG(default, ...) GET_FIRST_ARG_MACROS( \
,##__VA_ARGS__, \
GET_FIRST_ARG_4_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_3_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_2_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_1_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_0_ARGS(default, ##__VA_ARGS__), \
)
"0,"; GET_FIRST_ARG(0);
"0,1"; GET_FIRST_ARG(0,1);
"0,1,2"; GET_FIRST_ARG(0,1,2);
"0,1,2,3"; GET_FIRST_ARG(0,1,2,3);
"0,1,2,3,4"; GET_FIRST_ARG(0,1,2,3,4);
To see the output:
# 1 "test.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/x86_64-linux-gnu/include/stdc-predef.h" 1 3
# 1 "<command-line>" 2
# 1 "test.cpp"
# 16 "test.cpp"
"0,"; GET_FIRST_ARG_0_ARGS(0);
"0,1"; GET_FIRST_ARG_1_ARGS(0, 1);
"0,1,2"; GET_FIRST_ARG_2_ARGS(0, 1,2);
"0,1,2,3"; GET_FIRST_ARG_3_ARGS(0, 1,2,3);
"0,1,2,3,4"; GET_FIRST_ARG_4_ARGS(0, 1,2,3,4);
Now, a full working program would be:
#include <iostream>
#define GET_FIRST_ARG_0_ARGS(default) (default)
#define GET_FIRST_ARG_1_ARGS(default, a) (a)
#define GET_FIRST_ARG_2_ARGS(default, a, b) (a)
#define GET_FIRST_ARG_3_ARGS(default, a, b, c) (a)
#define GET_FIRST_ARG_4_ARGS(default, a, b, c, d) (a)
#define GET_FIRST_ARG_MACROS(default, a, b, c, d, macro, ...) macro
#define GET_FIRST_ARG(default, ...) GET_FIRST_ARG_MACROS( \
,##__VA_ARGS__, \
GET_FIRST_ARG_4_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_3_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_2_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_1_ARGS(default, __VA_ARGS__), \
GET_FIRST_ARG_0_ARGS(default, ##__VA_ARGS__), \
)
int main(int argc, char const *argv[]) {
"0,"; GET_FIRST_ARG(0);
"0,1"; GET_FIRST_ARG(0,1);
"0,1,2"; GET_FIRST_ARG(0,1,2);
"0,1,2,3"; GET_FIRST_ARG(0,1,2,3);
"0,1,2,3,4"; GET_FIRST_ARG(0,1,2,3,4);
std::cerr << "0, == " << GET_FIRST_ARG(0) << std::endl;
std::cerr << "0,1 == " << GET_FIRST_ARG(0,1) << std::endl;
std::cerr << "0,1,2 == " << GET_FIRST_ARG(0,1,2) << std::endl;
std::cerr << "0,1,2,3 == " << GET_FIRST_ARG(0,1,2,3) << std::endl;
std::cerr << "0,1,2,3,4 == " << GET_FIRST_ARG(0,1,2,3,4) << std::endl;
return 0;
}
Which would output the following by being compiled with g++ test.cpp -o test && ./test:
0, == 0
0,1 == 1
0,1,2 == 1
0,1,2,3 == 1
0,1,2,3,4 == 1
Note: It is important to use () around the macro contents as #define GET_FIRST_ARG_1_ARGS(default, a) (a) to not break in ambiguous expressions when a is just not a integer.
Extra macro for second argument:
#define GET_SECOND_ARG_0_ARGS(default) (default)
#define GET_SECOND_ARG_1_ARGS(default, a) (default)
#define GET_SECOND_ARG_2_ARGS(default, a, b) (b)
#define GET_SECOND_ARG_3_ARGS(default, a, b, c) (b)
#define GET_SECOND_ARG_4_ARGS(default, a, b, c, d) (b)
#define GET_SECOND_ARG_MACROS(default, a, b, c, d, macro, ...) macro
#define GET_SECOND_ARG(default, ...) GET_SECOND_ARG_MACROS( \
,##__VA_ARGS__, \
GET_SECOND_ARG_4_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_3_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_2_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_1_ARGS(default, __VA_ARGS__), \
GET_SECOND_ARG_0_ARGS(default, ##__VA_ARGS__), \
)
None of the above examples (from Derek Ledbetter, David Sorkovsky, and Joe D) to count arguments with macros worked for me using Microsoft VCC 10. The __VA_ARGS__ argument is always considered as a single argument (token-izing it with ## or not), so the argument shifting in which those examples rely doesn't work.
So, short answer, as stated by many others above: no, you can't overload macros or use optional arguments on them.

How to write a while loop with the C preprocessor?

I am asking this question from an educational/hacking point of view, (I wouldn't really want to code like this).
Is it possible to implement a while loop only using C preprocessor directives. I understand that macros cannot be expanded recursively, so how would this be accomplished?
If you want to implement a while loop, you will need to use recursion in the preprocessor. The easiest way to do recursion is to use a deferred expression. A deferred expression is an expression that requires more scans to fully expand:
#define EMPTY()
#define DEFER(id) id EMPTY()
#define OBSTRUCT(id) id DEFER(EMPTY)()
#define EXPAND(...) __VA_ARGS__
#define A() 123
A() // Expands to 123
DEFER(A)() // Expands to A () because it requires one more scan to fully expand
EXPAND(DEFER(A)()) // Expands to 123, because the EXPAND macro forces another scan
Why is this important? Well when a macro is scanned and expanding, it creates a disabling context. This disabling context will cause a token, that refers to the currently expanding macro, to be painted blue. Thus, once its painted blue, the macro will no longer expand. This is why macros don't expand recursively. However, a disabling context only exists during one scan, so by deferring an expansion we can prevent our macros from becoming painted blue. We will just need to apply more scans to the expression. We can do that using this EVAL macro:
#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__
Next, we define some operators for doing some logic(such as if, etc):
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x))
#define NOT_0 ~, 1,
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0
#define BOOL(x) COMPL(NOT(x))
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define IF(c) IIF(BOOL(c))
Now with all these macros we can write a recursive WHILE macro. We use a WHILE_INDIRECT macro to refer back to itself recursively. This prevents the macro from being painted blue, since it will expand on a different scan(and using a different disabling context). The WHILE macro takes a predicate macro, an operator macro, and a state(which is the variadic arguments). It keeps applying this operator macro to the state until the predicate macro returns false(which is 0).
#define WHILE(pred, op, ...) \
IF(pred(__VA_ARGS__)) \
( \
OBSTRUCT(WHILE_INDIRECT) () \
( \
pred, op, op(__VA_ARGS__) \
), \
__VA_ARGS__ \
)
#define WHILE_INDIRECT() WHILE
For demonstration purposes, we are just going to create a predicate that checks when number of arguments are 1:
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define IS_1(x) CHECK(PRIMITIVE_CAT(IS_1_, x))
#define IS_1_1 ~, 1,
#define PRED(x, ...) COMPL(IS_1(NARGS(__VA_ARGS__)))
Next we create an operator, which we will just concat two tokens. We also create a final operator(called M) that will process the final output:
#define OP(x, y, ...) CAT(x, y), __VA_ARGS__
#define M(...) CAT(__VA_ARGS__)
Then using the WHILE macro:
M(EVAL(WHILE(PRED, OP, x, y, z))) //Expands to xyz
Of course, any kind of predicate or operator can be passed to it.
Take a look at the Boost preprocessor library, which allows you to write loops in the preprocessor, and much more.
You use recursive include files. Unfortunately, you can't iterate the loop more than the maximum depth that the preprocessor allows.
It turns out that C++ templates are Turing Complete and can be used in similar ways. Check out Generative Programming
I use meta-template programming for this purpose, its fun once you get a hang of it. And very useful at times when used with discretion. Because as mentioned its turing complete, to the point where you can even cause the compiler to get into an infinite loop, or stack-overflow! There is nothing like going to get some coffee just to find your compilation is using up 30+ gigabytes of memory and all the CPU to compile your infinite loop code!
well, not that it's a while loop, but a counter loop, nonetheless the loop is possible in clean CPP (no templates and no C++)
#ifdef pad_always
#define pad(p,f) p##0
#else
#define pad0(p,not_used) p
#define pad1(p,not_used) p##0
#define pad(p,f) pad##f(p,)
#endif
// f - padding flag
// p - prefix so far
// a,b,c - digits
// x - action to invoke
#define n0(p,x)
#define n1(p,x) x(p##1)
#define n2(p,x) n1(p,x) x(p##2)
#define n3(p,x) n2(p,x) x(p##3)
#define n4(p,x) n3(p,x) x(p##4)
#define n5(p,x) n4(p,x) x(p##5)
#define n6(p,x) n5(p,x) x(p##6)
#define n7(p,x) n6(p,x) x(p##7)
#define n8(p,x) n7(p,x) x(p##8)
#define n9(p,x) n8(p,x) x(p##9)
#define n00(f,p,a,x) n##a(pad(p,f),x)
#define n10(f,p,a,x) n00(f,p,9,x) x(p##10) n##a(p##1,x)
#define n20(f,p,a,x) n10(f,p,9,x) x(p##20) n##a(p##2,x)
#define n30(f,p,a,x) n20(f,p,9,x) x(p##30) n##a(p##3,x)
#define n40(f,p,a,x) n30(f,p,9,x) x(p##40) n##a(p##4,x)
#define n50(f,p,a,x) n40(f,p,9,x) x(p##50) n##a(p##5,x)
#define n60(f,p,a,x) n50(f,p,9,x) x(p##60) n##a(p##6,x)
#define n70(f,p,a,x) n60(f,p,9,x) x(p##70) n##a(p##7,x)
#define n80(f,p,a,x) n70(f,p,9,x) x(p##80) n##a(p##8,x)
#define n90(f,p,a,x) n80(f,p,9,x) x(p##90) n##a(p##9,x)
#define n000(f,p,a,b,x) n##a##0(f,pad(p,f),b,x)
#define n100(f,p,a,b,x) n000(f,p,9,9,x) x(p##100) n##a##0(1,p##1,b,x)
#define n200(f,p,a,b,x) n100(f,p,9,9,x) x(p##200) n##a##0(1,p##2,b,x)
#define n300(f,p,a,b,x) n200(f,p,9,9,x) x(p##300) n##a##0(1,p##3,b,x)
#define n400(f,p,a,b,x) n300(f,p,9,9,x) x(p##400) n##a##0(1,p##4,b,x)
#define n500(f,p,a,b,x) n400(f,p,9,9,x) x(p##500) n##a##0(1,p##5,b,x)
#define n600(f,p,a,b,x) n500(f,p,9,9,x) x(p##600) n##a##0(1,p##6,b,x)
#define n700(f,p,a,b,x) n600(f,p,9,9,x) x(p##700) n##a##0(1,p##7,b,x)
#define n800(f,p,a,b,x) n700(f,p,9,9,x) x(p##800) n##a##0(1,p##8,b,x)
#define n900(f,p,a,b,x) n800(f,p,9,9,x) x(p##900) n##a##0(1,p##9,b,x)
#define n0000(f,p,a,b,c,x) n##a##00(f,pad(p,f),b,c,x)
#define n1000(f,p,a,b,c,x) n0000(f,p,9,9,9,x) x(p##1000) n##a##00(1,p##1,b,c,x)
#define n2000(f,p,a,b,c,x) n1000(f,p,9,9,9,x) x(p##2000) n##a##00(1,p##2,b,c,x)
#define n3000(f,p,a,b,c,x) n2000(f,p,9,9,9,x) x(p##3000) n##a##00(1,p##3,b,c,x)
#define n4000(f,p,a,b,c,x) n3000(f,p,9,9,9,x) x(p##4000) n##a##00(1,p##4,b,c,x)
#define n5000(f,p,a,b,c,x) n4000(f,p,9,9,9,x) x(p##5000) n##a##00(1,p##5,b,c,x)
#define n6000(f,p,a,b,c,x) n5000(f,p,9,9,9,x) x(p##6000) n##a##00(1,p##6,b,c,x)
#define n7000(f,p,a,b,c,x) n6000(f,p,9,9,9,x) x(p##7000) n##a##00(1,p##7,b,c,x)
#define n8000(f,p,a,b,c,x) n7000(f,p,9,9,9,x) x(p##8000) n##a##00(1,p##8,b,c,x)
#define n9000(f,p,a,b,c,x) n8000(f,p,9,9,9,x) x(p##9000) n##a##00(1,p##9,b,c,x)
#define n00000(f,p,a,b,c,d,x) n##a##000(f,pad(p,f),b,c,d,x)
#define n10000(f,p,a,b,c,d,x) n00000(f,p,9,9,9,9,x) x(p##10000) n##a##000(1,p##1,b,c,d,x)
#define n20000(f,p,a,b,c,d,x) n10000(f,p,9,9,9,9,x) x(p##20000) n##a##000(1,p##2,b,c,d,x)
#define n30000(f,p,a,b,c,d,x) n20000(f,p,9,9,9,9,x) x(p##30000) n##a##000(1,p##3,b,c,d,x)
#define n40000(f,p,a,b,c,d,x) n30000(f,p,9,9,9,9,x) x(p##40000) n##a##000(1,p##4,b,c,d,x)
#define n50000(f,p,a,b,c,d,x) n40000(f,p,9,9,9,9,x) x(p##50000) n##a##000(1,p##5,b,c,d,x)
#define n60000(f,p,a,b,c,d,x) n50000(f,p,9,9,9,9,x) x(p##60000) n##a##000(1,p##6,b,c,d,x)
#define n70000(f,p,a,b,c,d,x) n60000(f,p,9,9,9,9,x) x(p##70000) n##a##000(1,p##7,b,c,d,x)
#define n80000(f,p,a,b,c,d,x) n70000(f,p,9,9,9,9,x) x(p##80000) n##a##000(1,p##8,b,c,d,x)
#define n90000(f,p,a,b,c,d,x) n80000(f,p,9,9,9,9,x) x(p##90000) n##a##000(1,p##9,b,c,d,x)
#define cycle5(c1,c2,c3,c4,c5,x) n##c1##0000(0,,c2,c3,c4,c5,x)
#define cycle4(c1,c2,c3,c4,x) n##c1##000(0,,c2,c3,c4,x)
#define cycle3(c1,c2,c3,x) n##c1##00(0,,c2,c3,x)
#define cycle2(c1,c2,x) n##c1##0(0,,c2,x)
#define cycle1(c1,x) n##c1(,x)
#define concat(a,b,c) a##b##c
#define ck(arg) a[concat(,arg,-1)]++;
#define SIZEOF(x) (sizeof(x) / sizeof((x)[0]))
void check5(void)
{
int i, a[32769];
for (i = 0; i < SIZEOF(a); i++) a[i]=0;
cycle5(3,2,7,6,9,ck);
for (i = 0; i < SIZEOF(a); i++) if (a[i] != 1) printf("5: [%d] = %d\n", i+1, a[i]);
}
Here's an abuse of the rules that would get it done legally. Write your own C preprocessor. Make it interpret some #pragma directives the way you want.
I found this scheme useful when the compiler got cranky and wouldn't unroll certain loops for me
#define REPEAT20(x) { x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;}
REPEAT20( val = pleaseconverge(val) );
But IMHO, if you need something much more complicated than that, then you should write your own pre-preprocessor. Your pre-preprocessor could for instance generate an appropriate header file for you, and it is easy enough to include this step in a Makefile to have everything compile smoothly by a single command. I've done it.

Resources