在Define预处理指令中的字符串字面量

3
我希望你能将 #define 指令放在引号内进行翻译。问题如下:
我正在使用的嵌入式平台中有一个内置函数,它接受字面汇编代码作为字符串。我想将其封装成宏。
__asm__("goto 0x2400");

以上的内置函数会使处理器跳转到0x2400位置的代码并从该地址开始执行(对于那些想知道的人,我正在编写引导程序,这就是为什么这很必要)。因为地址在字符串中,所以我不能轻易地替换它。我需要一种方法使该函数通用化,以便我可以从任何地址开始执行代码。例如:

#define ASM_GOTO __asm__("goto X")

由于X在引号中,因此这不会导致正确的文本替换。有没有解决方法?

3个回答

10
#define ASM_GOTO(X) __asm__("goto " #X)

然而,这个有一个小问题:

#define MAGIC_ADDRESS 0x2400
ASM_GOTO(MAGIC_ADDRESS);

使用__asm__("goto " "MAGIC_ADDRESS");会导致结果为跳转到"MAGIC_ADDRESS",我认为这不是您想要的。

因此,

#define STRINGIZE(X) #X
#define ASM_GOTO(X) __asm__("goto " STRINGIZE(X))

可能更接近实际情况,因为在ASM_GOTO展开时,X会被展开,然后才会被STRINGIZE处理。

如果你还不知道,需要注意的是,虽然预处理器的结果是"goto " "0x2400"(两个字符串字面量),但它们在编译期间会合并为一个单独的字符串字面量(C99的5.1.1.2/6节)。这发生在宏被展开之后(第4步),但在语义分析之前(第7步)。


这个可行。谢谢你提供使用两个定义的想法。我在第一个定义处卡住了。 - jliu83

4

试试这个:

#define ASM_GOTO(X) __asm__("goto "#X)

如果您在另一个定义中定义了地址,则此方法无法正常工作。请参见所选答案以查看错误信息。 - jliu83
确实如此。但它对于最初发布的问题确实有效。如果您想要符号地址的扩展,那么您应该在问题中明确说明这一点。 - Paul R

1
你需要使用stringize运算符。类似这样:
#define ASM_GOTO(x) __asm("goto " #x)

应该做你需要它做的事情。


如果您在另一个定义中定义地址,则此方法无法正常工作。请参见所选答案以查看错误。 - jliu83

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接