Fortran 在没有显式接口的情况下,将未分配的数组传递给例程有什么问题吗?

Fortran 在没有显式接口的情况下,将未分配的数组传递给例程有什么问题吗?,fortran,subroutine,Fortran,Subroutine,考虑: program main real, allocatable, dimension(:) :: foo integer n n=10 call dofoo(foo,n,1) allocate(foo(n)) call dofoo(foo,n,0) end program main subroutine dofoo(foo,n,mode) real foo(n) integer i,n,mode if(mode.eq.1)then n=6 return endif do i=

考虑:

program main
real, allocatable, dimension(:) :: foo
integer n
n=10
call dofoo(foo,n,1)
allocate(foo(n))
call dofoo(foo,n,0)
end program main

subroutine dofoo(foo,n,mode)
real foo(n)
integer i,n,mode
if(mode.eq.1)then
   n=6
   return
endif
do i=1,n
   foo(i)=i
enddo
return
end subroutine dofoo

上面的代码有什么问题吗?(它与gfortran一起工作)我第一次传入了一个未分配的数组,但我没有碰它——标准中是否有任何东西会导致它以依赖于系统的方式运行?

您几乎已经回答了自己的问题。是的,根据标准,如果范围中没有接口,则将未分配的可分配数组作为实际参数传递总是非法的

如果在作用域中有接口,则只有当伪参数也是可分配的时才合法

是的,我被它咬了。我的解决方法是在调用之前将大小分配为零。

正确地指出问题中的使用是不允许的。不过,我们可以更精确一些。(括号中引用Fortran 2018标准。)

有三种情况可以使用未分配的可分配实际参数:

  • 当伪参数也是可分配的(仅在Fortran 2003或Fortran 95+TR-15581之后)(15.5.2.6 p.2)
  • 当伪参数是可选的普通参数时(仅从Fortran 2008开始)(15.5.2.12 p.1、15.5.2.4 p.7)
  • 当程序为内在查询功能时(15.5.2.4 p.7、16.1 p.2)
“未使用的”伪参数也不例外。这些限制适用于可分配参数是数组还是标量

任何其他用途表示程序不合格(15.5.2.4 p.7、15.5.2.7 p.2)

在一致性程序中,每个可接受的情况都有一个明确的可用接口。可分配或可选伪参数需要一个(15.4.2.2 p.1(3)),可访问的内在过程始终有一个可用的显式接口(15.4.2.1 p.1)

程序的这些要求不是编译器的要求。这种不一致的程序并不一定意味着您在编译和运行时会看到问题。在这个问题的程序中,它不会试图以一种不好的方式取消引用,你很可能会侥幸逃脱。然而,编写不一致的程序是不好的,依赖它们“工作”是非常糟糕的

有些方面可能会出现问题:

  • 运行时检查
  • 编译时检查
  • 具有
    属性的假人(同样,在这种情况下需要显式接口)
也就是说,对于某些编译器/编译器选项,程序的行为可能会有所不同。如果编译器注意到您应该有一个显式接口可用,它可能会拒绝编译该程序。如果运行时检查参数是否已分配,则程序在进入子例程时可能会中止。如果在未分配实际参数的情况下尝试使用
value
属性创建数组的匿名可定义副本,则运行时可能会执行一些非常意外的操作



对于这个问题,还有另一个需要担心的不合规问题。显式长度伪参数
foo(n)
意味着实际参数必须至少包含
n
元素。未分配的数组至少没有
n
元素(对于任何元素,甚至零,
n
)。如果
foo
intent(out)
编译器将有权对实际参数的这些元素进行“取消定义”。这可能会失败。

谢谢。我担心情况就是这样。我不知道该标准要说什么(我非常熟悉f77标准,但实际上我还没有阅读f90标准的大部分内容),作为旁注,上面的代码与gfortran一起工作(在我编辑掉错误之后),传递可分配数组直到对F95标准的TR才被清除。已分配状态和维度是可分配数组变量的一部分。这很重要,因为像intent(in)或intent(out)这样的事情不仅会告诉您数组的值是否可以更改,还会告诉您数组的大小或分配状态是否可以更改。如果没有显式接口,程序在传递可分配数组时将不得不假设最坏的情况——它甚至可能在返回时不再知道数组的大小。在通常情况下,这是一个巨大的性能损失,因此决定必须有显式接口。@JonathanDursi--你是说我甚至不能在没有显式接口的情况下将分配的数组传递给例程?--这对使用遗留代码有着巨大的影响。。。e、 g.我不能分配一个数组然后将其传递给BLAS…@mgilson no;只是它直到F95/F2003才被清除。Fortran委员会无情地、无情地、痴迷于向后兼容性,所以这通常是正常的,但正如Ian Bush指出的,有些情况下,如未分配的数组不起作用。这是有道理的;“未分配数组”在F90之前甚至不是一个东西,所以它自然不适用于F77代码。另一方面,来自某个调用例程的固定非负大小数组也可以。如果您正在做在F90之前无法完成的事情,则可能需要显式接口。如果不是,可能不是。