Fortran 中参数初始化的兼容性

compatibility of Parameter initialization in Fortran

我有一个很大的 Fortran 代码,它在命名常量(参数)声明中使用了 Merge 函数。但是,编译有问题。

为了说明问题,一个简单的代码是

CHARACTER*3,PARAMETER :: Mode = 'yes'  ! 'yes' or 'no'
INTEGER,PARAMETER :: L = merge(1,2, trim(Mode) .eq.'yes') 
INTEGER,DIMENSION(L) :: some_array 

(根据目的改变模式。 当然,实际代码更复杂。)

积分是 (1)参数'L'根据'Mode'初始化 (2)参数'L'用于定义其他数组

这个 'L' 的初始化对于最近的编译器是可以的。

然而,集群机器有旧版本(2013 年左右)的 Fortran 编译器, 它不接受 'L'.

这种初始化方式

如何在旧的 Fortran 标准中实现相同的效果?

给出的语句在 Fortran 2003 及更高版本中有效,但在 Fortran 90/95 中无效。

您确实希望使用支持 Fortran 2003(以及更晚的版本)的编译器,并且评论中提供了查找此内容的方法。无法保证这是您要编译的代码的唯一 Fortran 2003+ 部分。但是,这里有一个历史课程可以告诉我们解决方法。

首先,明显的解决方法是

integer, parameter :: L=1   ! Change to 2 if mode is 'no'

但这并不好。 (也如评论所述,您可以通过使用非 Fortran 预处理宏来改善这一点。)

正如其他地方所指出的,Fortran 2003 显着扩展了允许用于设置命名常量值的内容。在 Fortran 95 和 Fortran 2003 中,设置值的表达式都是 初始化表达式 。但是,在 Fortran 95 中,可能无法使用 merge(这是一个基本函数),因为只有当所有参数都是字符或整数时,标准基本函数才能出现在初始化表达式中:mask 参数是合乎逻辑的。 Fortran 2003 取消了这个限制。

您将无法根据 Fortran 95 规则重写初始化表达式。

这导致了第二种解决方法。

您想在 some_array 的数组规范中使用命名常量 L。但是,这里的数组规范只需要是一个(常量)规范表达式,不一定是L这样的常量。 Fortran 95 规范表达式比初始化表达式更宽松:

character(len=3), parameter :: Mode = 'yes'  ! 'yes' or 'no'
integer, dimension(merge(1,2, trim(Mode).eq.'yes')) :: some_array

这不如命名常量好。