编译器gfortran和ifort之间的区别(可分配数组和全局变量)

GPM*_*ler 5 fortran gfortran intel-fortran

代码

以下MWE描述了我想要使用的内容(请注意,我没有设计这个,我只是尝试使用某些代码,我通常不会使用全局变量).

PROGRAM MAIN
IMPLICIT NONE

  integer :: N
  real(8), allocatable :: a(:,:)

  N=3
  allocate(a(N,3))

  a=initialize_array()

  CONTAINS
    function initialize_array() result(a)
    IMPLICIT NONE
        real(8) :: a(N,3)
        a=1
    end function initialize_array  

END PROGRAM MAIN
Run Code Online (Sandbox Code Playgroud)

问题

gfortran给出了一个错误,它Error: Variable 'n' cannot appear in the expression at (1)指向real(8) :: a(N,3)函数内部.在一个子程序中它会起作用,那么问题可能在这里呢?

这个问题

为什么ifort(v.15.0.3)编译这个,而gfortran(v.4.8.4)没有?

fra*_*lus 5

正如其他人所评论的那样,很难说某些事情是否被明确允许:语言主要基于规则和限制条件.

所以,我不会证明代码没有错误(并且gfortran不允许拒绝它),但让我们来看看发生了什么.

首先,我会反对High Performance Mark给出的一件事,因为这有点相关:

具有依赖于变量值的维度的数组的声明,例如a(N,3),要求在编译时知道(或至少可知)变量的值.

显式形状数组的边界不必总是由常量表达式给出(我们松散地定义为"在编译时已知/可知"):在某些情况下,显式形状数组可以具有由变量给出的边界.这些被称为自动对象(以及由规范表达式给出的边界).

函数结果是允许自动对象的一个​​这样的地方.在函数结果声明的问题示例中,N主机关联并形成规范表达式.

a让我们看看gfortran如何响应程序的小修改,而不是用尽所有其他限制来看到真正允许的声明.

首先,gfortran对象的问题代码的修剪版本.

  integer n
contains
  function f() result(g)
     real g(n)
  end function f
end program
Run Code Online (Sandbox Code Playgroud)

功能结果f有名称g.我们称之为函数结果并不重要,所以当我们调用它时会发生什么f

  integer n
contains
  function f()
     real f(n)
  end function f
end program
Run Code Online (Sandbox Code Playgroud)

这对我来说很愉快.

如果我们在模块而不是主程序中构建第一个块,该怎么办?

module mod
  integer n
contains
  function f() result(g)
     real g(n)
  end function f
end module
Run Code Online (Sandbox Code Playgroud)

那也编译.

自然的结论是:即使gfortran是正确的(我们已经错过了一些隐藏得很好的约束)来拒绝第一个代码,它要么在拒绝其他代码时非常不一致,要么约束真的很奇怪.

  • 我几天前在comp.lang.fortran和Steve Kargl(gfortran开发人员)同意这是一个gfortran bug.https://groups.google.com/d/msg/comp.lang.fortran/xwh9SYKiQG0/73Ls_waxCgAJ我没时间创建报告. (2认同)