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

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

问题描述

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



我写了一个小例子程序:

 程序pgm 
调用a
结束

子例程a
隐式无
integer :: i
double precision :: fie

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

包含
子程序b
双精度:: x
!双精度:: fie
$ bx = i
x = x + fie( i)
写(*,*)x
结束子程序
结束子程序


双精度函数fie(ii)
隐含无
整数,意图(in):: ii

fie = ii
结束函数

在cygwin(gfortran 5.4.0)下使用gfortran编译时,出现以下错误消息:

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

x = x + fie(i)
1
错误:(1)处的'fie'不是函数

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



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

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

任何解释?

解决方案

最简单的解决方法是使用

  double precision,external :: fie 

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



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



感谢IanH的相关标准规则从Fortran 2008(16.5.1.4p5)开始,但Fortran 95将具有相同的功能):


如果外部或虚拟过程隐式接口是通过主机关联访问的
,那么它将在主机范围单元中具有EXTERNAL
属性
;如果它作为
中的一个函数在内部作用域单元中调用,则它的类型和类型参数应该在主机作用域单元中建立
。如果该作用域单元显式声明它们,调用
函数,从一个模块访问该函数,或访问该函数,那么具有EXTERNAL属性的
a函数的类型和类型参数在作用域
单元中建立(b

$ b $ p

当然,显式接口(它的类型和类型参数是
)最好使用模块)比外部函数好得多。

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

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.

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

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).

Any explanation?

解决方案

The simplest fix is to use

double precision, external :: fie

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

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.

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

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天全站免登陆