力学 Fortran 预处理器

Posted

技术标签:

【中文标题】力学 Fortran 预处理器【英文标题】:Mechanics Fortran Preprocessor 【发布时间】:2014-11-13 02:13:39 【问题描述】:

我最近碰巧遇到了当今大多数 Fortran 编译器支持的预处理选项(如 Fortran Wiki 中所述)。来自 C 背景,我想更好地了解与 (Fortran-) 预处理器的 #include 指令相关的机制和注意事项。

从一开始就避免任何混淆:Fortran 中有两个 include 指令(参见例如 F77 reference)

include "foo" 是编译器指令,即 foo 只能包含 Fortran 语句 #include "bar" 是一个预处理指令,即 bar 可以包含 #defines

我知道这种差异,我只对第二种情况感兴趣(因此我的问题不是this post 的重复)。

我将用一个例子来解释我的问题:假设我们有两个文件,一个头文件 (macro.h) 和一个源文件 (display.F):

宏.h

#define MSG() say_hello()

display.F

#include "macro.h"

    PROGRAM display
    CALL MSG()
    CALL another_message()
    END

    SUBROUTINE say_hello()
    WRITE(*,*) 'Hello.'
    END

    SUBROUTINE another_message()
    CALL MSG()
    END

这是我的问题:

范围

如果我包含 macro.h,则定义宏 MSG() 的位置(全局、本地 SUBROUTINE 等)是:

    在文件的开头(如上)? 在PROGRAM display 的开头(没有其他地方)? 在例如开头SUBROUTINE another_message()(别无他处)?

从测试看来:1. 全局,2. 在PROGRAM 和所有SUBROUTINES,3. 在那个SUBROUTINE 中。对这些假设的确认和一些理论上的解释为什么会很棒。

上述 (1. - 3.) 中哪些是预处理器的最佳实践包括?

包括警卫

如果我有一个多文件项目并且我在多个 *.F 源文件中包含 header.h,我是否需要提供包含保护?

如果上述问题的答案取决于编译器(因为预处理不是 Fortran 标准),我最感兴趣的是 ifort 的行为。

【问题讨论】:

【参考方案1】:

规则与您知道的 C 预处理器相同。 GCC 甚至对 C 和 Fortran 使用相同的 cpp(对于传统模式下的 Fortran)。因此没有范围,一切都只是一个文本,预处理器不关心程序单元。

因此,1.、2. 和 3. 从定义位置到文件结束或直到 #undef 都是有效的。它们在递归 #included 文件中也有效。

如果守卫是指#undef,那么是的,否则会出现有关重新定义的警告或错误,但前提是您将所有这些文件都包含在一个文件中。如果他们是独立的,那么没有。

关键是将预处理器视为文本替换工具。它对 Fortran一无所知

最后一点,预处理器是非标准的,但可以广泛使用。

【讨论】:

以上是关于力学 Fortran 预处理器的主要内容,如果未能解决你的问题,请参考以下文章

Fortran 预处理器指令用法

cmake可以自动添加fortran预处理器-cpp标志吗?

预处理器和使用关联

将 Fortran 转换为 C 或 C++

Fortran 中的变量识别问题

如何在 Fortran 中将 OpenACC 与 cublasDgetrfBatched 接口?