【问题标题】:Concatenating an expanded macro and a word using the Fortran preprocessor使用 Fortran 预处理器连接扩展宏和单词
【发布时间】:2016-12-20 13:30:52
【问题描述】:

我正在尝试将源代码中的单词与预处理器宏的扩展连接起来。基本上我在代码中的某处有foo,而#define EXPANSION bar 我想获得foobar。但是,我正在努力寻找一种适用于所有编译器的方法。目前,如果它可以与 gfortran 和 ifort 一起使用,我会很高兴。

根据其documentation,gfortran 预处理器是一个以“传统模式”运行的C 预处理器,它没有## 标记粘贴操作符。但是,使用空的 C 样式 /**/ 注释可以获得相同的效果。 ifort 预处理器的行为似乎更像普通的 C 预处理器,所以普通的标记粘贴在 ifort 中可以解决问题。不幸的是,空的 /**/ 评论在 ifort 中不起作用,因为评论被替换为一个空格。

这是一个小例子:

#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#define PASTE(x,y) x ## y

foo/**/EXPANSION   
CAT(foo,EXPANSION)

gfortran 生成:

foobar
foo ## bar

虽然 ifort 给了我:

foo bar
foobar

当然,我可以通过检查两个编译器的预定义宏来选择正确的方法:

#ifdef __GFORTRAN__
foo/**/EXPANSION
#else
CAT(foo,EXPANSION)
#endif

这对他们俩都有效,但是让预处理器为每个扩展设置条件是相当丑陋的。我宁愿避免这种情况,并且在开始时只使用一次宏魔法。

我在另一个问题上看到this answer,这可能会让我解决这个问题,但我宁愿找到一个不单独调用预处理器的解决方案。

我对 C 预处理器不太熟悉。也许有一种简单的方法可以做我想做的事。有什么想法吗?

编辑:我已经尝试过这样的事情:

#define EXPANSION bar
#define CAT(x,y) PASTE(x,y)
#ifdef __GFORTRAN__
#define PASTE(x,y) x/**/y
#else
#define PASTE(x,y) x ## y
#endif

CAT(foo,EXPANSION)

不幸的是,这在生成fooEXPANSION 的 gfortran 中不起作用。我不完全确定这是如何工作的,但显然 CAT 宏的扩展阻止了 EXPANSION 在同一行中的扩展。我怀疑这是“传统”C 预处理器的一个特性......

【问题讨论】:

  • 我认为答案是定义一个依赖于编译器的CONCAT 函数。这可用于所有扩展。详情见this answer
  • 感谢您的建议。我已经尝试过这样的事情(请参阅问题的编辑)。不幸的是,无法让它工作......
  • 奇怪,x/**/y 产生 fooEXPANSION,但 `x/**/ y` 产生 foo bar。我建议制定这个问题,以便它吸引 C 预处理器专家并且他们不会跳过它,因为他们会认为它是 Fortran 特定的(事实并非如此)。
  • 我想我明白这一点。 CAT 的扩展首先发生,产生 fooEXPANSIONEXPANSION 这个词将不会被进一步扩展,因为它没有被空格分隔。如果您在y 之前添加一个额外的空格,则CAT 的扩展将产生foo EXPANSION,它将进一步扩展为foo bar

标签: macros fortran c-preprocessor gfortran intel-fortran


【解决方案1】:

我做了一些研究,似乎基本上大多数 Fortran 编译器(即 Intel 和 PGI)都使用带有标记粘贴运算符的相对普通的 C 预处理器。我们只需要对 gfortran 进行特殊处理,它在传统模式下使用 C 预处理器,没有标记粘贴操作符。

感谢entry on c-faq.com,我发现CAT 宏的定义适用于我迄今为止测试的所有编译器:

#ifdef __GFORTRAN__
#define PASTE(a) a
#define CAT(a,b) PASTE(a)b
#else
#define PASTE(a) a ## b
#define CAT(a,b) PASTE(a,b)
#endif

另一个解决方案(仍然使用/**/ 技巧)由Jonathan Lefflerthis answer 中发布到相关问题。

【讨论】:

  • 所以它类似于我最初建议的字符串化技巧......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
  • 1970-01-01
  • 2020-10-18
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
相关资源
最近更新 更多