如何在宏中转义#
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" )
有助于理解问题的本质。 #
符号在三个方面对预处理器来说是特殊的:
第一个预处理标记为 #
的源代码行被预处理器识别为不是 "text line"。也就是说,它包含预处理器的指令。另一方面,文本行是要处理的数据——主要是 C 程序源,但可能包含要扩展的宏。如果 #
不是行中的第一个预处理标记,那么它在这个意义上并不特殊。
类函数宏替换列表的预处理标记中,标记#
是字符串化运算符。然而,它在类似变量的宏中并没有达到这个目的,在重新扫描宏扩展文本以进行进一步的宏替换时也没有。
在类函数宏替换列表的预处理标记中,标记##
是标记粘贴操作符。然而,它在类似变量的宏中并没有达到这个目的,在重新扫描宏扩展文本以进行进一步的宏替换时也没有。
你无法逃避 #
对预处理器 本身 的重要性,但你仍然可以通过使用一些间接的方式来实现你想要的宏,如@昆汀示范。首先,如果 #
出现在类似函数的宏的扩展中,那么它不能直接出现在该宏的替换文本中,否则它将被解释为字符串化运算符。它必须通过扩展另一个宏来引入。其次,如果它必须紧靠其他文本且中间没有空格,那么扩展到它的直接宏本身必须是一个类似函数的宏,以便括号用于将宏名称与相邻文本分开。这需要二级间接。
我需要写一个需要内联汇编的宏
#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" )
有助于理解问题的本质。 #
符号在三个方面对预处理器来说是特殊的:
第一个预处理标记为
#
的源代码行被预处理器识别为不是 "text line"。也就是说,它包含预处理器的指令。另一方面,文本行是要处理的数据——主要是 C 程序源,但可能包含要扩展的宏。如果#
不是行中的第一个预处理标记,那么它在这个意义上并不特殊。类函数宏替换列表的预处理标记中,标记
#
是字符串化运算符。然而,它在类似变量的宏中并没有达到这个目的,在重新扫描宏扩展文本以进行进一步的宏替换时也没有。在类函数宏替换列表的预处理标记中,标记
##
是标记粘贴操作符。然而,它在类似变量的宏中并没有达到这个目的,在重新扫描宏扩展文本以进行进一步的宏替换时也没有。
你无法逃避 #
对预处理器 本身 的重要性,但你仍然可以通过使用一些间接的方式来实现你想要的宏,如@昆汀示范。首先,如果 #
出现在类似函数的宏的扩展中,那么它不能直接出现在该宏的替换文本中,否则它将被解释为字符串化运算符。它必须通过扩展另一个宏来引入。其次,如果它必须紧靠其他文本且中间没有空格,那么扩展到它的直接宏本身必须是一个类似函数的宏,以便括号用于将宏名称与相邻文本分开。这需要二级间接。