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 :-)