losang
losang

Reputation: 85

How to escape a # in a macro

I need to write a macro which needs to inline assembly

#define create_me(name) \
  __asm\
  mov name,#0x1021\
  __endasm\

The # however isn't compiling. I have tried passing it in as a parameter however that doesn't work too. It says invalid preprocessor token . I can try to use an inline function but I can't dynamically create the register name. That is I don't have access to the name variable. Does anyone have any suggestions on how to use the # operation inside a macro.

I have looked at Escaping a # symbol in a #define macro?, but I have clearly explained why I need the macro here. My usecase is different.

Upvotes: 3

Views: 3338

Answers (4)

John Bollinger
John Bollinger

Reputation: 181689

It helps to understand the nature of the problem. The # symbol is special to the preprocessor in three ways:

  1. A source line whose first preprocessing token is # is recognized by the preprocessor as not being a "text line". That is, it contains instructions for the preprocessor. Text lines, on the other hand, are the data to be processed -- mostly C program source, but possibly containing macros to be expanded. The # is not special in this sense if it is not the first preprocessing token on the line.

  2. Among the preprocessing tokens of the replacement list for a function-like macro, the token # is the stringification operator. It does not serve that purpose in a variable-like macro, however, nor when macro-expanded text is re-scanned for further macro replacement.

  3. Among the preprocessing tokens of the replacement list for a function-like macro, the token ## is the token-pasting operator. It does not serve that purpose in a variable-like macro, however, nor when macro-expanded text is re-scanned for further macro replacement.

You cannot escape the significance of the # to the preprocessor per se, but you can nevertheless implement your desired macro by employing a bit of indirection, as @Quentin demonstrated. In the first place, if a # is to appear in the expansion of a function-like macro then it cannot appear directly in that macro's replacement text, where it would be interpreted as the stringification operator. It must instead be introduced by expanding another macro. In the second place, if it must abut other text without whitespace between, then the immediate macro that expands to it must be a function-like macro itself, so that the parentheses serve to separate the macro name from the abutting text. That requires a second level of indirection.

Upvotes: 0

n. m. could be an AI
n. m. could be an AI

Reputation: 120079

For SDCC, use the new __asm__ format.

#define create_me(name) \
      __asm__( "mov "    #name    ", #0x1021" )

Upvotes: 2

Quentin
Quentin

Reputation: 63154

Using an indirection through another macro should do the trick:

#define HASH_LIT #
#define HASH() HASH_LIT

#define create_me(name) \
  __asm\
  mov name,HASH()0x1021\
  __endasm

Upvotes: 6

David Ranieri
David Ranieri

Reputation: 41045

Preprocessor commands/directives always begin with a sharp sign (#), you can not use it for your own symbols.

If you want to create a variable named whatever0x1021 use the token concatenation ##:

#include <stdio.h>

#define create_me(name) name ## 0x121

int main(void)
{
    int create_me(a); /* int a0x121; */

    return 0;
}

Upvotes: 0

Related Questions