包含子例程中变量和函数的作用域规则

时间:2016-11-19 18:35:11

标签: fortran fortran95

我有一个问题,理解为什么在子例程中声明的变量(i)在包含的子例程中被看到,但对于导致编译的函数(fie),这不是真的错误。我搜索了一个答案,并试图看看我是否能在Fortran 95标准中找到一些东西但是徒劳无功。

我写了一个小例子程序:

program pgm
  call a
end

subroutine a
  implicit none
  integer :: i
  double precision :: fie

  i = 7
  call b
  !write(*,*) fie(9)

contains
  subroutine b
    double precision :: x
    !double precision :: fie

    x = i
    x = x + fie(i)
    write(*,*) x
  end subroutine
end subroutine


double precision function fie(ii)
  implicit none
  integer, intent(in) :: ii

  fie = ii
end function

在cygwin(gfortran 5.4.0)下使用gfortran编译时,我收到以下错误消息:

$ gfortran aa.f90
aa.f90:20:15:

     x = x + fie(i)
               1
Error: ‘fie’ at (1) is not a function

启用任何一条注释行时,程序将编译并正确运行。

使用英特尔编译器(英特尔Fortran 12.1.7.367,确实很老)时,我看到了类似的错误消息。

看起来fie必须在包含的例程中可用,或者必须在包含子例程中使用,但正如我所说,我无法在网络或Fortran 95标准中找到答案(或者我没有找到合适的词语。)

有任何解释吗?

1 个答案:

答案 0 :(得分:2)

最简单的解决方法是使用

double precision, external :: fie

外部属性(也可以由external语句指定)说:这是一个过程,我没有声明一个局部变量。

对于不将external解释为函数声明的声明,函数体必须存在函数引用。内部功能不算数。因此编译器创建了一个名为fie的本地双精度变量。

感谢IanH的相关标准规则(来自Fortran 2008(16.5.1.4p5),但Fortran 95将具有相同的标准):

  

如果带有隐式接口的外部或虚拟过程是   通过主机关联访问,然后它应具有外部   主机范围单元中的属性;如果它作为函数调用   内部范围单元,其类型和类型参数应为   在主机范围内建立。的类型和类型参数   在作用域中建立具有EXTERNAL属性的函数   如果该作用域单元显式声明它们,则调用   功能,从模块访问功能,或访问   函数来自其主机的类型和类型参数   建立的。

当然,显式接口(最好使用模块)比外部函数好得多。