预处理器宏字符串化

preprocessor macro stringify

我正在尝试了解预处理器。

为什么波纹管预处理器宏中的一个不起作用而另一个却起作用

#pragma 和 _Pragma 有什么区别

为什么我们用 ASTRINGZ 包裹 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

why one of the bellow preprocessor macro doesn't work while the other does

虽然预处理器将扩展当前扩展产生的大多数宏,但它只会执行一个扩展步骤。所以 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() for TODO (...) 被交还给预处理器。此时一切都应该适当扩展。

what is the difference between #pragma and _Pragma

_Pragma 是提供编译器特定 pragma 指令的另一种标准方法。区别在于 _Pragma 可以是宏扩展的结果,而 #pragma 可能不是指令。

why do we wrap STRINGZ with ASTRINGZ?

这是另一种延迟技巧。如果 ASTRINGZ 的参数本身是一些非平凡的预处理器扩展的结果。