Fortran 函数指定输入和输出数组的大小以及 gfortran 边界检查

Fortran function specifying size of input and output arrays and gfortran bounds check

假设我有以下 Fortran 程序

program foobar
implicit none

interface
    pure function foo (var1, var2) result(ans)
        implicit none
        integer, dimension(:),          intent(in) :: var1
        integer, dimension(size(var1)), intent(in) :: var2
        integer, dimension(product(var1 + var2)) :: ans
    end function foo

    pure function bar (n, var1, var2) result(ans)
         implicit none
         integer,                        intent(in) :: n
         integer, dimension(:),          intent(in) :: var1
         integer, dimension(size(var1)), intent(in) :: var2
         integer, dimension(n)                      :: ans
   end function bar
end interface

write (*,*) foo([1, 1, 1], [2, 2, 2])
! write (*,*) bar(27, [1, 1, 1], [2, 2, 2])   
end program foobar

pure function foo (var1, var2) result(ans)
     implicit none
     integer, dimension(:),          intent(in) :: var1
     integer, dimension(size(var1)), intent(in) :: var2
     integer, dimension(product(var1 + var2))   :: ans
     ans = 0
end function foo

pure function bar (n, var1, var2) result(ans)
     implicit none
     integer,                        intent(in) :: n
     integer, dimension(:),          intent(in) :: var1
     integer, dimension(size(var1)), intent(in) :: var2
     integer, dimension(n) :: ans
     ans = 0
end function bar

如果我用

编译这段代码
gfortran -fcheck=all -o bbb bbb.F08

然后我在执行过程中得到以下错误

Fortran runtime error: Array bound mismatch for dimension 1 of array 'var2' (0/3)

如果我省略 -fcheck=all 选项,代码编译并运行得很好。如果我在主程序中注释第一个 write 并取消注释第二个,代码编译并运行正常,无论我是否使用 -fcheck=all 选项。我无法检查其他编译器,因为 gfortran 是我目前唯一可以访问的编译器。

据我了解,编译器无法确定数组的大小,因此在运行时检查失败。这种解释正确吗?其次,关于我可以在 dimension() 声明中放置什么,是否有一些规则,以便编译器仍然可以在运行时进行一些边界检查?我应该始终显式传递数组的大小吗?这样我可能会解决这些问题,但是这会使调用这些函数变得非常麻烦。

这是一个编译器错误,已在最新版本中修复。在我的电脑上,它因 gfortran 4 而失败。7.and 在 gfortran-5 的预发布版中运行正常。

首先,回答结果变量 ans.

dimension 声明中可以包含什么

ans 是显式数组,因此您提供的边界必须是 规范表达式 。因为它是一个结果变量,所以它不需要是一个常量表达式,只是一个限制表达式。 Fortran 2008 7.1.11.

中给出了有关如何构成限制表达式的详细信息

让我们看看组成表达式product(var1 + var2)的东西。如果这是一个受限表达式,您可以照原样使用它。

var1var2 是没有 intent(out)optional 属性的虚拟变量。所以这很好。接下来是什么?

+这里是内在的操作。打钩。使 var1+var2 成为受限表达式。

product是一个标准内函数,不是规范查询函数,它的参数是一个限制表达式,在这种情况下它的结果是一个标量整数表达式。

所以,总而言之:没关系。

而且,正如 Vladimir F 所说:这是一个编译器错误。这只是证实它不是程序员的错误。