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)
的东西。如果这是一个受限表达式,您可以照原样使用它。
var1
和 var2
是没有 intent(out)
和 optional
属性的虚拟变量。所以这很好。接下来是什么?
+
这里是内在的操作。打钩。使 var1+var2
成为受限表达式。
product
是一个标准内函数,不是规范查询函数,它的参数是一个限制表达式,在这种情况下它的结果是一个标量整数表达式。
所以,总而言之:没关系。
而且,正如 Vladimir F 所说:这是一个编译器错误。这只是证实它不是程序员的错误。
假设我有以下 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)
的东西。如果这是一个受限表达式,您可以照原样使用它。
var1
和 var2
是没有 intent(out)
和 optional
属性的虚拟变量。所以这很好。接下来是什么?
+
这里是内在的操作。打钩。使 var1+var2
成为受限表达式。
product
是一个标准内函数,不是规范查询函数,它的参数是一个限制表达式,在这种情况下它的结果是一个标量整数表达式。
所以,总而言之:没关系。
而且,正如 Vladimir F 所说:这是一个编译器错误。这只是证实它不是程序员的错误。