Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C Macro - how to get an integer value into a string literal [duplicate]

I think it's good to have a stringifying macro in your utils header:

#define STR_IMPL_(x) #x      //stringify argument
#define STR(x) STR_IMPL_(x)  //indirection to expand argument macros

Then you can keep the macro numerical and stringify it on the spot:

#define LEDS 48 
int x = LEDS;   

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, "STR(LEDS)"       \n\t"
...
}

The above preprocesses to:

int x = 48;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, ""48""       \n\t"
...
}

which relies on the fact that adjacent string literals get concatenated.


You can avoid the stringification macro mess if you use a constraint:

#define LEDS 48

void DrawFrame()
{
    asm volatile(
    "ldi R18, %[leds]"
    : : [leds] "M" (LEDS) : "r18");
}

You need two auxiliary macros for this to work. Then you can take advantage of automatic string concatenation:

#define STR(x) #x
#define EXPAND(x) STR(x)

#define LEDS 48
int x = LEDS;

void DrawFrame()
{
    asm(
    "ldi        R27, 0x00       \n\t"
    "ldi        R26, 0x00       \n\t"
    "ldi        R18, " EXPAND(LEDS) "       \n\t"
...
}

The reason for using two macros is that the first alone won't expand the parameter passed in.

If you just did this:

printf("LEDS = " STR(LEDS) "\n");

It would expand to this:

printf("LEDS = " "LEDS" "\n");

The EXPAND macro allows the parameter passed in to be substituted as well.

So then this:

printf("LEDS = " EXPAND(LEDS) "\n");

Would expand to this:

printf("LEDS = " "48" "\n");