Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible for C preprocessor macros to contain preprocessor directives?

I would like to do the equivalent of the following:

#define print_max(TYPE) \ #  ifdef TYPE##_MAX \      printf("%lld\n", TYPE##_MAX); \ #  endif  print_max(INT); 

Now the #ifdef or any nested preprocessor directive is not allowed as far as I can see in a function macro. Any ideas?

Update: So it seems like this is not possible. Even a hack to check at runtime seems unachievable. So I think I'll go with something like:

#ifndef BLAH_MAX #  define BLAH_MAX 0 #endif # etc... for each type I'm interested in  #define print_max(TYPE) \     if (TYPE##_MAX) \        printf("%lld\n", TYPE##_MAX);  print_max(INT); print_max(BLAH); 
like image 204
pixelbeat Avatar asked Nov 19 '08 12:11

pixelbeat


People also ask

Are macros preprocessor directives?

There are 4 Main Types of Preprocessor Directives: Macros. File Inclusion. Conditional Compilation. Other directives.

Are preprocessor directives used for macro expansion?

The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation. It is called a macro processor because it allows you to define macros, which are brief abbreviations for longer constructs.

Does C have preprocessor directives?

The C preprocessor modifies a source file before handing it over to the compiler, allowing conditional compilation with #ifdef, defining constants with #define, including header files with #include, and using builtin macros such as __FILE__.

Which preprocessor directive is used to define a macro?

The #define directive is used to define values or macros that are used by the preprocessor to manipulate the program source code before it is compiled.


1 Answers

The Boost Preprocessor (which works for C as well as C++, even though Boost as a whole is a C++ library) library can help with this kind of task. Instead of using an #ifdef within a macro (which isn't permitted), it helps you include a file multiple times, with different macros defined each time, so that the file can use #ifdef.

The following code, if saved to max.c, should do what you want for each of the words listed in the MAXES #define at the top of the file. However, it won't work if any of the _MAX values are floating point, since the preprocessor can't handle floating point.

(Boost Processor is a handy tool, but it's not exactly straightforward; you can decide whether or not this approach is an improvement over copy-and-paste.)

#define MAXES (SHRT)(INT)(LONG)(PATH)(DOESNT_EXIST)  #if !BOOST_PP_IS_ITERATING  /* This portion of the file (from here to #else) is the "main" file */  #include <values.h> #include <stdio.h> #include <boost/preprocessor.hpp>  /* Define a function print_maxes that iterates over the bottom portion of this  * file for each word in MAXES */ #define BOOST_PP_FILENAME_1 "max.c" #define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MAXES))) void print_maxes(void) { #include BOOST_PP_ITERATE() }  int main(int argc, char *argv[]) {     print_maxes(); }  #else  /* This portion of the file is evaluated multiple times, with  * BOOST_PP_ITERATION() resolving to a different number every time */  /* Use BOOST_PP_ITERATION() to look up the current word in MAXES */ #define CURRENT BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(), MAXES) #define CURRENT_MAX BOOST_PP_CAT(CURRENT, _MAX)  #if CURRENT_MAX printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is %lld\n", (long long) CURRENT_MAX); #else printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is undefined\n"); #endif  #undef CURRENT #undef CURRENT_MAX  #endif 
like image 62
Josh Kelley Avatar answered Sep 19 '22 01:09

Josh Kelley