包含的子例程中的变量和函数的范围规则 [英] Scoping rules for variable and functions in contained subroutines

查看:9
本文介绍了包含的子例程中的变量和函数的范围规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a problem understanding why a variable (i) declared in a subroutine is seen in a contained subroutine, but that this is not true for a function (fie) which results in a compilation error. I searched for an answer and also tried to see if I could find something in the Fortran 95 standard but in vain.

我写了一个小例子程序:

I wrote a small example program:

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 编译时,我收到以下错误消息:

When compiling this with gfortran under cygwin (gfortran 5.4.0) I get the following error message:

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

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

当启用任一注释行时,程序编译并正确运行.

When enabling either of the commented lines the program compiles and runs correctly.

我在使用 Intel 编译器时看到了类似的错误消息(Intel Fortran 12.1.7.367,确实很旧).

I saw a similar error message when using the Intel compiler (Intel Fortran 12.1.7.367, indeed quite old).

看起来 fie 必须在包含的例程中可用,或者必须在包含的子例程中使用,但如上所述,我在网上或 Fortran 中找不到答案95 标准(或者我没有找到正确的词).

It looks like fie has to be made available either in the contained routine or has to be used in the encompassing subroutine, but as said I could not find an answer on the net or in the Fortran 95 standard (or maybe I didn't look for the right words).

有什么解释吗?

推荐答案

最简单的解决方法是使用

The simplest fix is to use

double precision, external :: fie

外部属性(也可以通过external语句指定)说:这是一个过程,我不是在声明一个局部变量.

the external attribute (also can be specified by the external statement) says: this is a procedure, I am not declaring a local variable.

对于没有external 的声明被解释为函数声明,函数引用必须存在于函数体内.内部函数不算.因此编译器创建了一个名为 fie 的局部双精度变量.

For the declaration without the external to be interpreted as a function declaration the function reference must be present within the function body. Internal functions don't count. And therefore the compiler created a local double precision variable called fie.

感谢 IanH 提供相关的标准规则(来自 Fortran 2008 (16.5.1.4p5),但 Fortran 95 将有一个等效规则):

Thank's to IanH for the relevant standard rule (from Fortran 2008 (16.5.1.4p5), but Fortran 95 will have an equivalent):

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

If an external or dummy procedure with an implicit interface is accessed via host association, then it shall have the EXTERNAL attribute in the host scoping unit; if it is invoked as a function in the inner scoping unit, its type and type parameters shall be established in the host scoping unit. The type and type parameters of a function with the EXTERNAL attribute are established in a scoping unit if that scoping unit explicitly declares them, invokes the function, accesses the function from a module, or accesses the function from its host where its type and type parameters are established.

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

Of course explicit interfaces (best using modules) are much better than external functions.

这篇关于包含的子例程中的变量和函数的范围规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆