Is there a way to evaluate an expression before stringification in c?
example:
#define stringify(x) #x
...
const char * thestring = stringify( 10 *
You need to interpret the string. C doesn't do that by itself, look up a library that'll do it for you.
http://expreval.sourceforge.net/ http://www.codeproject.com/KB/library/expreval.aspx
There are others, just search google.
The C preprocessor cannot do that, so use snprintf
instead:
char *stringify(int n) {
char *res = malloc(12);
snprintf(res, 12, "%d", n);
return res;
}
const char *thestring = stringify(10 * 50);
For simplicity's sake I've omitted error control and free
.
As the other responses have said, this cannot be done with the C preprocessor. This is one of the many shortcomings of C that are solved by C++, This is the sort of thing that can be accomplished in a very elegant manner using Template Metaprogramming.
To calculate an arithmetic expression at compile time:
#include <boost/mpl/arithmetic.hpp>
namespace mpl = boost::mpl;
int main(int argc, char *argv[]) {
const int n = mpl::multiplies<mpl::int_<10>, mpl::int_<50> >::value;
return 0;
}
Here's a string formatting metafunction I found on the boost mailing list archives. This version will convert an int (like the one calculated above) into a string in a base of your choosing:
#include <boost/mpl/string.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/push_back.hpp>
namespace mpl = boost::mpl;
struct itoa_ct
{
// radix for _itoa() goes up to 36, but only bother with 16 here
typedef mpl::vector_c<char
,'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'
> radix_t;
template <int Radix, unsigned int Quotient>
struct radix_convert
{
typedef typename mpl::push_back<
typename radix_convert<Radix, Quotient / Radix>::type
, mpl::char_<mpl::at_c<radix_t, Quotient % Radix>::type::value>
>::type type;
};
template <int Radix>
struct radix_convert<Radix, 0>
{
typedef mpl::string<> type;
};
template <int I, int Radix = 10>
struct apply
{
// All bases != 10 consider I as unsigned
typedef typename radix_convert<
Radix, static_cast<unsigned int>((Radix == 10 && I < 0) ? -I : I)
>::type converted_t;
// Prefix with '-' if negative and base 10
typedef typename mpl::if_<
mpl::bool_<(Radix == 10 && I < 0)>
, mpl::push_front<converted_t, mpl::char_<'-'> >
, mpl::identity<converted_t>
>::type::type type;
};
};
Putting the two together your expression becomes:
const char *thestring = mpl::c_str<itoa_ct::apply<mpl::multiplies<mpl::int_<10>, mpl::int_<50> >::value>::type>::value;
... and this all gets turned into nothing more than a constant string "500" at compile time :-)
I'll take a wild guess that you have more experience in scripting languages than in C.
There are multiple phases you have to be aware of with a purely compiled language like C: Preproccesing, Compiling, Linking, and Running
First the preprocessor is run. That is where your macro gets expanded. At this point, its contents are "10 * 50". Not much to be done about that.
After the macro pre-processor completes, then the compiler converts the program into an object file
After the compiler finishes on every source file, the linker steps in and slaps them all together.
Finally, when your user is ready, they execute your program. Semanticly, this is when the 10 * 50 gets calculated. (In actuality, most compilers will recognize that this will always be the same value, and replace it with 500, but that's an implementation detail).
Scripting languages like to blur all these lines, so I can see where someone used to one of those might be confused.
You could write a script (perl?) to use as preprocessor which recognizes the strings to evaluate, evaluates them and then it calls the true cpp on the "evaluated" file.
Maybe it could work.
You probably won't like the format in which the expression is going to be presented, yes, it is possible, but in a very eclectic way - you'd need to create a separate functional language that is being "run" by the preprocessor. The proof:
$ cvs -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp login
$ cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P chaos-pp
$ cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P order-pp
$ cd order-pp/example
$ grep -A 6 'int main' fibonacci.c
int main(void) {
printf
("The 500th Fibonacci number is "
ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0)))))
".\n");
return 0;
}
$ cpp -I../inc fibonacci.c 2>/dev/null | grep -A 6 'int main'
int main(void) {
printf
("The 500th Fibonacci number is "
"139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"
".\n");
return 0;
}
In this example we have newly-made preprocessor-run purely functional language being used to calculate 500th Fibonacci number and then stringize it to give to C compiler.
Of course I very much doubt that this is something that you'd ever use in practice, and it is a very far stretched abuse of the preprocessor, but I consider it to be a very thought-provoking hack. (and yes, without the exotic theoretical twists like this one, it's not possible).