Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stringify an expression in C

Tags:

c

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?

like image 715
Andrew Avatar asked Aug 13 '09 22:08

Andrew


3 Answers

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.

like image 69
T.E.D. Avatar answered Oct 13 '22 14:10

T.E.D.


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.

like image 10
dfa Avatar answered Nov 17 '22 19:11

dfa


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

like image 5
Andrew Y Avatar answered Nov 17 '22 20:11

Andrew Y