包含的子例程中变量和函数的作用域规则
Scoping rules for variable and functions in contained subroutines
我无法理解为什么在子例程中声明的变量 (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
当启用任一注释行时,程序会正确编译和运行。
我在使用Intel编译器(Intel Fortran 12.1.7.367,确实很老)时看到了类似的错误信息。
看起来 fie
必须在包含的例程中可用,或者必须在包含的子例程中使用,但如前所述,我无法在网上或 Fortran 95 中找到答案标准(或者我没有找合适的词)。
有什么解释吗?
最简单的修复方法是使用
double precision, external :: fie
外部属性(也可以通过external
语句指定)表示:这是一个过程,我没有声明局部变量。
要将没有 external
的声明解释为函数声明,函数引用必须存在于函数体内。内部功能不算数。因此,编译器创建了一个名为 fie
.
的局部双精度变量
感谢 IanH 提供相关标准规则(来自 Fortran 2008 (16.5.1.4p5),但 Fortran 95 将具有等效规则):
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.
当然,显式接口(最好使用模块)比外部函数要好得多。
我无法理解为什么在子例程中声明的变量 (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
当启用任一注释行时,程序会正确编译和运行。
我在使用Intel编译器(Intel Fortran 12.1.7.367,确实很老)时看到了类似的错误信息。
看起来 fie
必须在包含的例程中可用,或者必须在包含的子例程中使用,但如前所述,我无法在网上或 Fortran 95 中找到答案标准(或者我没有找合适的词)。
有什么解释吗?
最简单的修复方法是使用
double precision, external :: fie
外部属性(也可以通过external
语句指定)表示:这是一个过程,我没有声明局部变量。
要将没有 external
的声明解释为函数声明,函数引用必须存在于函数体内。内部功能不算数。因此,编译器创建了一个名为 fie
.
感谢 IanH 提供相关标准规则(来自 Fortran 2008 (16.5.1.4p5),但 Fortran 95 将具有等效规则):
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.
当然,显式接口(最好使用模块)比外部函数要好得多。