如何在宏中转义#

How to escape a # in a macro

我需要写一个需要内联汇编的宏

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

但是 # 没有编译。我试过将它作为参数传递,但这也不起作用。它说无效的预处理器令牌。我可以尝试使用内联函数,但无法动态创建寄存器名称。那就是我无权访问名称变量。有没有人对如何在宏中使用#操作有任何建议。

我看过Escaping a # symbol in a #define macro?,但我已经清楚地解释了为什么我需要这里的宏。我的用例不同。

预处理器 commands/directives 总是以尖锐的符号 (#) 开头,您不能将它用于您自己的符号。

如果要创建名为 whatever0x1021 的变量,请使用 token concatenation ##:

#include <stdio.h>

#define create_me(name) name ## 0x121

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

    return 0;
}

通过另一个宏使用间接应该可以解决问题:

#define HASH_LIT #
#define HASH() HASH_LIT

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

对于 SDCC,使用新的 __asm__ 格式。

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

有助于理解问题的本质。 # 符号在三个方面对预处理器来说是特殊的:

  1. 第一个预处理标记为 # 的源代码行被预处理器识别为不是 "text line"。也就是说,它包含预处理器的指令。另一方面,文本行是要处理的数据——主要是 C 程序源,但可能包含要扩展的宏。如果 # 不是行中的第一个预处理标记,那么它在这个意义上并不特殊。

  2. 类函数宏替换列表的预处理标记中,标记#是字符串化运算符。然而,它在类似变量的宏中并没有达到这个目的,在重新扫描宏扩展文本以进行进一步的宏替换时也没有。

  3. 在类函数宏替换列表的预处理标记中,标记##是标记粘贴操作符。然而,它在类似变量的宏中并没有达到这个目的,在重新扫描宏扩展文本以进行进一步的宏替换时也没有。

你无法逃避 # 对预处理器 本身 的重要性,但你仍然可以通过使用一些间接的方式来实现你想要的宏,如@昆汀示范。首先,如果 # 出现在类似函数的宏的扩展中,那么它不能直接出现在该宏的替换文本中,否则它将被解释为字符串化运算符。它必须通过扩展另一个宏来引入。其次,如果它必须紧靠其他文本且中间没有空格,那么扩展到它的直接宏本身必须是一个类似函数的宏,以便括号用于将宏名称与相邻文本分开。这需要二级间接。