预处理程序宏stringify

时间:2019-01-28 11:50:28

标签: c compilation c-preprocessor pragma

我试图了解预处理器。

为什么下面的预处理器宏之一不起作用而另一个则不起作用

#pragma和_Pragma有什么区别

为什么我们用STRRINGZ包装STRINGZ?

enter image description here

#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

1 个答案:

答案 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的参数本身是某些非平凡的前体扩展的结果。