[ACCEPTED]-How can I generate a list via the C preprocessor (cpp)?-c-preprocessor

Accepted answer
Score: 20

The normal way of doing this with the preprocessor 4 is to define all the functions in a macro 3 that takes another macro as an argument, and 2 then use other macros to extract what you 1 want. For your example:

#define FUNCTION_TABLE(F) \
    F(f1, { some code }) \
    F(f2, { some code }) \
    F(f3, { some code }) \
:

    F(f99, { some code }) \
    F(f100, { some code })

#define DEFINE_FUNCTIONS(NAME, CODE)     int NAME() CODE
#define FUNCTION_NAME_LIST(NAME, CODE)   NAME,

FUNCTION_TABLE(DEFINE_FUNCTIONS)
int (*function_table)(void)[] = { FUNCTION_TABLE(FUNCTION_NAME_LIST) };
Score: 6

If you have a C99 complying compiler, the 5 preprocessor has variable length argument 4 lists. P99 has a preprocessor P99_FOR that can do 3 "code unrolling" like the one 2 you want to achieve. To stay close to your 1 example

#define MYFUNC(DUMMY, FN, I) int FN(void) { return I; } 
#define GENFUNCS(...)                                          \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_IGN, MYFUNC, __VA_ARGS__) \
int (*function_table)(void)[] = { __VA_ARGS__ }

GENFUNCS(toto, hui, gogo);

would expand to the following (untested)

int toto(void) { return 0; } 
int hui(void) { return 1; }
int gogo(void) { return 2; }
int (*function_table)(void)[] = { toto, hui, gogo };
Score: 2

This is sort of abuse of CPP but a common 5 type of abuse. I handle situations like 4 this by defining dummy macros

#define FUNCTIONS \
 foo(a,b,c,d) \
 foo(a,b,c,d) \
 foo(a,b,c,d)

now, 

#define foo(a,b,c,d) \
 a+b ;

FUNCTIONS

#undef foo

later, when 3 you want something different done with the 2 same list

#define foo(a,b,c,d) \
 a: c+d ;

FUNCTIONS

#undef foo

It's a bit ugly and cumbersome, but 1 it works.

Score: 2

There's this thing called X Macro which is used 5 as:

a technique for reliable maintenance 4 of parallel lists, of code or data, whose 3 corresponding items must appear in the same 2 order

This is how it works:

    #include <stdio.h>

//you create macro that contains your values and place them in (yet) not defined macro
#define COLORS\
    X(red, 91)\
    X(green, 92)\
    X(blue, 94)\

//you can name that macro however you like but conventional way is just an "X"

//and then you will be able to define a format for your values in that macro
#define X(name, value) name = value,
typedef enum { COLORS } Color;
#undef X //so you redefine it below

int main(void)
{
    #define X(name, value) printf("%d, ", name);
    COLORS
    #undef X
    return 0;
}

Solution for your 1 problem would be:

#define FUNCTIONS \
F(f1, code1)\
F(f2, code2)\
F(f3, code3)

#define F(name, code) int name(void){code}
FUNCTIONS
#undef F


#define F(name, code) &name,
int (*function_table[])(void) = { FUNCTIONS };
#undef F
Score: 0

Boost is a C++ library, but it's Preprocessor 4 module should still be good for use in C. It 3 offers some surprisingly advanced data types 2 and functionality for use in the preprocessor. You 1 could check it out.

More Related questions