Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preprocessor functions evaluated at compile time in C

I want to write preprocessor functions/arrays that are evaluated at compile time. For example, if I define

#define MYARR[] {5,4,3,2,1,0}

then, the code

int x = R[0];

should be presented as

int x = 5;

to the compiler. (Of course only literals can be used in the index). This is important if code size/memory is critical and we don't want to store MYARR, but we need it for coding convenience.

Compile time functions would also be good. For example, something like

#define MYMAP(n)
#if n==1
5
#else
2

So, the statement

int x = MYMAP(4);

should be presented to the compiler as

int x = 2;

Obviously, we have to use a literal as the argument. Is this possible?

like image 322
highBandWidth Avatar asked Sep 24 '10 21:09

highBandWidth


2 Answers

Sure its possible. While you could do that manually, Boost.Preprocessor already gives you the tools you need:

#include <boost/preprocessor.hpp>
#define SEQ (5)(4)(3)(2)(1)(0)
int x = BOOST_PP_SEQ_ELEM(0, SEQ);

... gets transformed to:

int x = 5;

It also includes arithmetic, comparisons and control structures like IF, FOR, FOR_EACH, enumerations, ... You just have to keep in mind that the data types you can work with are rather limited.

Utilizing Boost.PP again, your second example can be done like so:

#define MYMAP(x) BOOST_PP_IF(BOOST_PP_EQUAL(x, 1), 5, 2)

You can of course implement manually what Boost.PP does, but considering the time and effort needed for this i personally wouldn't bother.

As a C user, you won't be interested in the rest of Boost, so you might want to use bcp to extract the preprocessor components.

like image 191
Georg Fritzsche Avatar answered Oct 06 '22 13:10

Georg Fritzsche


The standard C preprocessor will not do what you want. To get this sort of behavior reliably you are going to need a more powerful, nonstandard preprocessing tool. However, I'm not familiar enough with what's available to direct you to which one you might want.

Although, in the second case, you may still be able to get the effect you want on most modern compilers. For example:

#define MYMAP(n) (((n) == 1) ? 5 : 2)

int x = MYMAP(4);

will still be presented to the compiler as:

int x = ((4 == 1) ? 5 : 2);

but the compiler itself, if it is a reasonable modern compiler and you allow it to optimize, will likely notice that this expression can be evaluated at compile-time and will emit code that is identical to

int x = 2;

However, there's nothing that guarantees that a compiler will perform this optimization.

like image 32
Tyler McHenry Avatar answered Oct 06 '22 15:10

Tyler McHenry