Macro-producing macros in C?

2019-01-20 09:12发布

问题:

I'd like to get the C preprocessor to generate macros for me (i.e., I'm using C99 only). I'd write a macro

#define make_macro(in) <...magic here...>

and when I put

make_macro(name1)
make_macro(name2)

later in the code, it would expand to

#define name1(...) name1_fn(name1_info, __VA_ARGS__)
#define name2(...) name2_fn(name2_info, __VA_ARGS__)

and I'd then be able to use name1 and name2 as (macro-implemented) functions. I think I'm stuck using macros at both steps: it makes sense to use a macro to repeatedly re-fill a template, and the variadic argument handling won't work except via a macro.

So what goes into the <...magic here...> placeholder to do this? At this point, I'm starting to believe that it's not possible in C99, but perhaps I'm missing some details of syntax.

回答1:

It's not possible in standard C.



回答2:

Have you considered using M4 macros? I think they are available on most platforms so that should not be a limitation.

M4 GNU page



回答3:

It's not possible because the macro is done only once.

This doesn't mean you could not use other macros in your macro but you could not do

#define TEST #define HALLO 33

int x = TEST;

and expect x to be 33 afterwards! What you would get is a syntax error because you tried

int x = #define HALLO 33;

Or maybe the compiler already complains about #define in #define.



回答4:

As everybody has said, you can't do exactly what you are asking for.

You might be able to do something like that by forcing the C preprocesor to run twice, e.g., with a rule like this in the makefile:

.c.pp:
   $(CPP) $< -o $@

Then give your file the extension of test.pp. The Makefile will run it once to generate the .c file, and then the normal run on the .c file will run it a second time.

Personally, I would rather write an external script in Perl or something to generate the C code for me; it's a bit cleaner than playing games with the C pre-processor. It depends on how much code we are talking about.



回答5:

Try #define make_macro(name,...) name##_fn(name##_info, __VA_ARGS__).

Use like this:

make_macro(name1)
make_macro(name2,1)

and this would generate

name1_fn(name1_info)
name2_fn(name2_info,1)


回答6:

As per C99 Section 6.10.3.2:

Each # preprocessing token in the replacement list for a function-like macro shall be followed by a parameter as the next preprocessing token in the replacement list.

So, you could certainly put a #define in a macro if you have a parameter named define but it will never do what you desire. This often bugs me since I have to work in C and as such can't use C++ templates.