我试图了解预处理器。
为什么下面的预处理器宏之一不起作用而另一个则不起作用
#pragma和_Pragma有什么区别
为什么我们用STRRINGZ包装STRINGZ?
#define STRINGZ(x) #x
#define ASTRINGZ(x) STRINGZ(x)
#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))
#define msg(s) TODO( s " - @ - " ASTRINGZ(__FILE__))
msg ("This doesnt work")
#pragma message "but this does: " ASTRINGZ(__FILE__)
来源:
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
http://forums.codeguru.com/showthread.php?215151-LINE-MACRO-to-string-literal&p=613574#post613574
答案 0 :(得分:1)
为什么下面的预处理器宏之一不起作用而另一个则不起作用
尽管预处理器将扩展当前扩展产生的大多数其他宏,但它只会执行单个扩展步骤。因此,ASTRINGZ(__FILE__)
在传递给TODO
的字符串化之前不会完全扩展。
您可以通过多种方法来处理此问题,最简单的方法是依靠事实__FILE__
已经是字符串文字。
#define msg(s) TODO( s " - @ - " __FILE__)
但是,如果您想尝试宏扩展,可以尝试使用延迟技术。这将延迟TODO
实际扩展本身的时间,并使参数有时间自行扩展。
#define EMPTY()
#define DEFER(m) m EMPTY EMPTY()()
#define msg(s) DEFER(TODO)( s " - @ - " ASTRINGZ(__FILE__))
上面的方法使( s " - @ - " ASTRINGZ(__FILE__))
不是宏的参数,因此ASTRINGZ
将被扩展。 DEFER(TODO)
是宏,因此它将扩展为TODO EMPTY EMPTY()()
。这将需要两个扩展周期(EMPTY()
的每个TODO (...)
都将交还给预处理器。这时,所有内容都应正确扩展。
#pragma和_Pragma有什么区别
_Pragma
是提供特定于编译器的编译指示的另一种标准方法。区别在于_Pragma
可能是宏扩展的结果,而#pragma
可能不是指令。
为什么我们用STRRINGZ包装STRINGZ?
这是另一种延期技术。如果ASTRINGZ
的参数本身是某些非平凡的前体扩展的结果。