Muperman
Muperman

Reputation: 384

Use C macro to create string with #

I'm working with a microcontroller and want to write a macro that inserts a specific number of wait cycles. I want

DELAY_CYCLES(40)

to expand to

__asm(" RPT #40 || NOP");

Additional restrictions:

  1. Since this is a compiler-specific intrinsic it needs to match exactly. I can't rely on the compiler to merge strings. E.g. __asm(" RPT #""40"" || NOP"); is not correct.

  2. The manufacturer headers already define: #define NOP __asm(" NOP")

  3. I can't pass a string to the intrinsic. char str = " RPT #40 || NOP"; __asm(str); is not allowed.

At the moment I am not even sure if there is a solution to this special case.

Upvotes: 0

Views: 430

Answers (1)

nneonneo
nneonneo

Reputation: 179382

It's quite probable that your compiler will concatenate the string literals properly (despite point #1); GCC and Clang, for instance, will do this. In this case, the simple solution is the following macro:

#define DELAY_CYCLES(X) __asm(" RPT #" #X " || NOP");

But, on the rare occasion when you really need to create a single string, then you may consider some hackery like this:

#define A(X) __asm(#X)
#define B(X) A(X || NOP)
#define HASH #
#define DELAY_CYCLES(X) B(RPT HASH X)

DELAY_CYCLES(40) expands to __asm("RPT # 40 || NOP"), even with NOP defined as something else. The space between # and 40 cannot, to my knowledge, be elided with this technique unless you want to write DELAY_CYCLES(#40) or your preprocessor allows you to paste # and 40 together (GCC does not).

Upvotes: 2

Related Questions