【问题标题】:C preprocessor macro: concatenation (example for Fortan90)C 预处理器宏:连接(Fortan90 的示例)
【发布时间】:2012-04-25 18:17:22
【问题描述】:

我遇到了以下问题:

我有以下两个正确的工作宏(扩展到 Fortran90 代码):

#define ld_dx(A)   (  (A(ixp1)-A(ix  ))/(dx)  )
#define rd_dx(A)   (  (A(ix  )-A(ixm1))/(dx)  )

(注意:这些宏依赖于以下附加宏:

#define ix    2:nx-1
#define ixp1  1+ix+1
#define ixm1 -1+ix-1

它们也依赖于声明:

integer, parameter :: nx = 100, dx = 1

)

在我的代码中,我可以通过调用来使用这些宏,例如

X = X + ld_dx(Y)

或:

X = X + rd_dx(Y)

现在我希望能够通过编写 d_dx(A,l) 来调用 ld_dx(A),并通过编写 d_dx(A,r) 来调用 rd_dx(A)。因此,该示例将如下所示:

X = X + d_dx(Y,l)

或

X = X + d_dx(Y,r)

=> 我正在寻找可以提供这种语法糖的 CPP 宏(以尽可能接近数学符号)。

最直接的做法是:

#define d_dx(A,s)  s ## d_dx(A)

不幸的是,这不起作用。 CPP 转换

d_dx(Y,l)

进入:

l ## Y)

通过研究其他与 CPP 连接相关的问题,我尝试了很多东西,但我无法弄清楚。非常感谢您的帮助!

山姆

PS:请注意,我也可以将宏“ld_dx(A)”和“rd_dx(A)”重命名为“dl_dx(A)”和“dr_dx(A)” 对此,最直接的做法是:

#define d_dx(A,s)  d ## s ## _dx(A)

不幸的是,这也不起作用:CPP 转换

d_dx(Y,l)

进入:

d ## l ## _dx(Y) 
  1

错误:在 (1) 处的表达式中应有右括号

即根本不执行串联。

【问题讨论】:

  • 你坚持使用宏而不是函数有什么特别的原因吗?
  • 是的,因为我们正在做超级计算,并且(在我们的例子中)函数不能像“直接代码”那样优化。
  • `函数不能像“直接代码”那样优化。 ' 我也做超级计算,这种说法简直是愚蠢。
  • 好吧,我承认我的陈述没有很好地表述。我只是不想讨论这个问题,所以我做了一个快速的大致解释。然而,我们有理由去做我们所做的事情......

标签: fortran concatenation c-preprocessor


【解决方案1】:
#define PASTE(x,y) x##y
#define d_dx(A,s) PASTE(s,d_dx)(A)

标记粘贴(## 运算符)和字符串化(# 运算符)禁止替换相邻参数,因此您必须分两步完成。

【讨论】:

  • 我试过'#define d_dx(A,s) PASTE(s,d_dx(A))'。为什么这不起作用?
  • 此解决方案适用于 IMB XL 编译器和 intel 编译器。不幸的是,我现在不得不发现这个解决方案不适用于 gfortran 调用的 c 预处理器(我试过:gcc 版本 4.6.2 (GCC)、gcc 版本 4.4.4 (GCC)、gcc 版本 4.1 .2 20070115(SUSE Linux))。问题与上面“PS”中描述的相同:根本不执行实际的连接。我们的目标是让代码与任何常见的编译器一起工作。如果我们也能找到适用于 gcc 编译器的解决方案,我将不胜感激。非常感谢您。
  • gfortran 文档说 cpp 是在传统模式下调用的。也许这里讨论的两个选项之一会有所帮助:c-faq.com/cpp/oldpaste.html.
  • 如果是这样,使用条件编译来选择旧版本和新版本。 #ifdef __STDC__ 是一个开始。
【解决方案2】:

尝试不使用空格。一些预处理器会忽略 ## 两侧的空格,而另一些则不会。

#define d_dx(A,s)  d##s##_dx(A)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-09
    • 2011-04-22
    • 1970-01-01
    • 2014-04-02
    • 2011-01-26
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    相关资源
    最近更新 更多