使用 Fortran 预处理器连接扩展宏和单词 [英] Concatenating an expanded macro and a word using the Fortran preprocessor

查看:25
本文介绍了使用 Fortran 预处理器连接扩展宏和单词的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to concatenate a word in the source code with the expansion of a preprocessor macro. Basically I have foo somewhere in the code, and with a #define EXPANSION bar I want to obtain foobar. However, I'm struggling to find a way to do this, which works with all compilers. For the moment I would be happy if it works with gfortran and ifort.

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

According to its documentation, the gfortran preprocessor is a C preprocessor running in "traditional mode", which does not have the ## token paste operator. However, the same effect can be obtained with an empty C-style /**/ comment. The ifort preprocessor seems to behave more like the normal C preprocessor, so normal token pasting does the trick in ifort. Unfortunately the empty /**/ comment does not work in ifort, as the comment is replaced by a single space instead.

这是一个小例子:

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

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

gfortran 生成:

For which gfortran produces:

foobar
foo ## bar

虽然 ifort 给了我:

While ifort gives me:

foo bar
foobar

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

Of course I could choose the right way by checking the predefined macros for both compilers:

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

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

This works for both of them, but it's rather ugly to have the preprocessor conditional for every expansion. I would much rather avoid this and have some macro magic only once in the beginning.

我已经看到 this answer 对另一个问题,这可能会让我解决这个问题,但我会而是找到一个不单独调用预处理器的解决方案.

I have seen this answer to another question, which would probably allow me to work around this issue, but I would rather find a solution that does not invoke the preprocessor separately.

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

I'm not too familiar with the C preprocessor. Maybe there is a simple way to do what I want. Any ideas?

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

I've already tried something like this:

#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 预处理器的一个特性......

Unfortunately this does not work in gfortran where it produces fooEXPANSION. I'm not entirely sure how this works, but apparently the expansion of the CAT macro prevents the expansion of EXPANSION in the same line. I suspect that this is a feature of the "traditional" C preprocessor ...

推荐答案

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

I have done some research and it seems that basically most Fortran compilers (i.e. Intel and PGI) use a relatively normal C-preprocessor with a token pasting operator. We only need a special treatment for gfortran, which uses a C preprocessor in traditional mode without a token pasting operator.

感谢 c-faq.com 上的条目,我找到了以下定义一个 CAT 宏,适用于我目前测试过的所有编译器:

Thanks to an entry on c-faq.com I found this definition of a CAT macro that works with all compilers I tested so far:

#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 Leffler 发布this answer 中对相关问题.

Another solution (that still uses the /**/ trick) was posted by Jonathan Leffler in this answer to a related question.

这篇关于使用 Fortran 预处理器连接扩展宏和单词的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆