我正在尝试理解预处理器。
为什么波纹管预处理器宏中的一个不起作用,而另一个却起作用
#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
的参数本身是一些非平凡的预处理器扩展的结果。
关于c - 预处理器宏字符串化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54401398/