我正在定义一个宏,该宏的计算结果为常量字符串,保存文件名和行号,用于记录目的。
它工作正常,但我只是不明白为什么需要 2 个额外的宏 -STRINGIFY
and TOSTRING
,当直觉简单地表明__FILE__ ":" #__LINE__
.
#include <stdio.h>
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define THIS_ORIGIN (__FILE__ ":" TOSTRING(__LINE__))
int main (void) {
/* correctly prints "test.c:9" */
printf("%s", THIS_ORIGIN);
return 0;
}
对我来说,这似乎是一个丑陋的黑客行为。
有人可以详细解释一下逐步发生的事情吗?__LINE__
字符串化正确,为什么两者都没有__FILE__ ":" STRINGIFY(__LINE__)
and __FILE__ ":" #__LINE__
works?
因为展开的顺序。这海湾合作委员会文档 http://gcc.gnu.org/onlinedocs/gcc-4.6.1/cpp/Argument-Prescan.html says:
宏参数在替换到宏体中之前会被完全宏扩展,除非它们被字符串化或与其他标记一起粘贴。替换后,将再次扫描整个宏体(包括替换的参数)以查找要扩展的宏。结果是参数被扫描两次以扩展其中的宏调用。
因此,如果参数将被字符串化,则不会首先对其进行扩展。您将得到括号中的文字。但如果它被传递给另一个宏,它就会被扩展。因此如果你想扩展它,你需要两级宏。
这样做是因为有些情况下你会这样做not想要在字符串化之前扩展参数,最常见的是assert()
宏。如果你写:
assert(MIN(width, height) >= 240);
你希望消息是:
Assertion MIN(width, height) >= 240 failed
而不是 MIN 宏扩展成的一些疯狂的东西(在 gcc 中它使用了几个 gcc 特定的扩展并且相当长的 IIRC)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)