c - 预处理器宏字符串化

标签 c compilation c-preprocessor pragma

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

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

#pragma 和 _Pragma 有什么区别

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

最佳答案

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/

相关文章:

源代码中的条件编译

c - 删除字符串数组项并移动 c 中的其余项

c - 将 printf/printk 消息重定向到文件

c++ - 在Mac OS X Lion(10.8.2)上使用Xcode 4.6安装OpenCV。

c - 在 C 中的 scanf 中使用定义(类型说明符)

c - GNU cpp 是否奇怪地为零参数的宏解释 C99 标准?

c - 使用 rand() 时输出范围内的随机数

android - 使用 Stock Android (Froyo) 时出现编译错误?

c - 64位机器中的对齐不是8字节

c - 当条件为假时,为什么条件包含中的受控组在词汇上有效?