tags:

views:

942

answers:

7

Is there a way to evaluate an expression before stringification in c?

example:

#define stringify(x)  #x
...
const char * thestring = stringify( 10 * 50 );

The problem is that I want to get

const char * thestring = "500";

And not:

const char * thestring = "10 * 50";

Can this be done?

A: 

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.

Kristoffon
No, he doesn't. Read the question more carefully.
SLaks
+1  A: 

Preprocessor macros are run before the compiler. It is, by definition, not possible to do exactly what you'retrying to do.

To convert a number into a string at runtime, call the itoa function, like this:

char thestring[8];

itoa(10 * 50, thestring, 10);

Note that this code declares thestring as an array, not a pointer. For more information, read about memory management in C.

SLaks
`itoa` isn't a standard C function, though.
caf
+7  A: 

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;
}

Usage

const char *thestring = stringify(10 * 50);

NB

For simplicity's sake I've omitted error control and free.

dfa
Ditch the "as far as I know" bit. The pre-processor runs before the compiler. The expression is calcualted semanticly at runtime (although the compiler should optimize it to a single constant at compile time).
T.E.D.
Because you omitted `free`, @Andrew's code will probably leak memory.
SLaks
Other than that, you're quite right.
SLaks
@SLaks: that is why I've added a **NB**
dfa
OBS: 10 bytes are not enough. You need at least 12, counting the zero-terminator and the leading - for negative integers.
Enno
@Enno, fixed thanks :)
dfa
+3  A: 

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.

T.E.D.
A: 

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.

tr3
+3  A: 

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:[email protected]:/cvsroot/chaos-pp login 
$ cvs -z3 -d:pserver:[email protected]:/cvsroot/chaos-pp co -P chaos-pp
$ cvs -z3 -d:pserver:[email protected]:/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).

Andrew Y
A: 

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

David Claridge
This is very nice, but it's probably not what the OP is looking for.
SLaks
No probably not, just pointing out that you can get around these things with C++ :-) As Andrew Y demonstrated you can do this sort of thing in C if you go to the extent of writing a language based solely on macros.
David Claridge