Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I stringify macros that are the results of operations on macros?

Here's a program that illustrates my problem:

#include <stdio.h>

#define NUMERATOR 8
#define DENOMINATOR 2
#define QUOTIENT (NUMERATOR / DENOMINATOR)

#define ZSTR(x) XSTR(#x)
#define YSTR(x) XSTR(x)
#define XSTR(x) STR(x)
#define STR(x) #x

int main()
{
    printf("QUOTIENT:       %d\n", QUOTIENT);
    printf("STR(QUOTIENT):  %s\n", STR(QUOTIENT));
    printf("XSTR(QUOTIENT): %s\n", XSTR(QUOTIENT));
    printf("YSTR(QUOTIENT): %s\n", YSTR(QUOTIENT));
    printf("ZSTR(QUOTIENT): %s\n", ZSTR(QUOTIENT));
    return 0;
}

And here's its output:

$ gcc -g -Wall -o stringify stringify.c && ./stringify 
QUOTIENT:       4
STR(QUOTIENT):  QUOTIENT
XSTR(QUOTIENT): (8 / 2)
YSTR(QUOTIENT): (8 / 2)
ZSTR(QUOTIENT): "QUOTIENT"

I would like to have a the string literal "4" passed to the compiler, but I'm losing hope. This is related to this question, but adds a level.

like image 639
nmichaels Avatar asked Aug 19 '11 19:08

nmichaels


1 Answers

You can define macros that paste together their arguments and then define a (large) number of other macros that do the evaluation as kind of a table lookup:

#define DIV(X, Y)  DIV_(X, Y)
#define DIV_(X, Y) DIV_##X##_##Y
#define DIV_0_1  0
#define DIV_1_1  1
#define DIV_2_1  2
    :
#define DIV_8_2  4
    :

This is kind of tedious, but you can easily write a little program to generate a header file with the above stuff in it and run that as part of your build process. Then you just need

#define QUOTIENT  DIV(NUMERATOR, DENOMINATOR)

Note that his kind of thing only works for unsigned integers -- if you need negative numbers or floating point, it won't work

like image 115
Chris Dodd Avatar answered Sep 22 '22 23:09

Chris Dodd