module - Fortran - 模块子例程参数意图混淆 - INOUT 与 OUT

标签 module scope fortran subroutine

假设有一个向量:

REAL(KIND=dp), DIMENSION(maxn) ::  rho

在初始子程序中分配值(连同 dpmaxn)并从主程序中调用。

然后主程序调用一个包含(不同的)子例程的模块来进化rhorho 的子例程参数定义为:

SUBROUTINE sum_density(a, b, c, ....., rho)

在此子例程中,rho 声明为:

REAL(KIND=dp), DIMENSION(maxn), INTENT(OUT)  ::  rho   

然而,在与 rho 关联的任何值之前,代码包含以下行:

foo1= foo2*foo3(i)/rho(i)

我原以为模块子例程不会访问主程序中定义的rho。我希望编译器会提示并要求将意图更改为 (INOUT) 或说 rho 之类的内容未定义。即使我将其更改为 (INOUT),结果也没有区别。模块子例程必须在主程序中访问 rho 的值并使用它,即使意图被声明为 OUT

我的问题是 - 在这种情况下,使用 INTENT(OUT)INTENT(INOUT) 有什么区别?

最佳答案

使用 INTENT(OUT) 程序不符合标准,因为它访问具有未定义值的数组。

但是,软件实现可能会起作用,因为显式形状数组通常是通过传递数组地址来实现的。如果您传递的数组是不连续的,假设

  rho(::2)

编译器很可能会创建一个副本,该副本被通过并且您可能会遇到问题,因为数组可能包含 intent(out) 的垃圾。

关于警告,它们不是强制性的,但如果您使用 -warn-Wall 等标志,编译器会对此发出警告。

对于 intent(in),当您尝试修改 rho 时,差异就会出现。如果您尝试编译器必须发出错误。

关于范围:

这里说作用域是不正确的,原来的rho肯定不在子程序的作用域内,只有dummy argument在。重复使用相同的名称可能会造成混淆。想象一下,它们实际上在程序中称为 rho1,在子例程中称为 rho2。那么很明显rho1不在子程序的范围内,但是rho2在。

现在,rho2 不能保证在带有 intent(out) 的子例程开始时具有与 rho1 相同的值,但是它保证有 intent(inout)。原因是参数传递可以使用复制输入和复制输出来实现,并且对于 intent(out) 可以省略复制。

考虑这段代码:

module m
contains
  subroutine sub(a2)
    real, intent(out) :: a2(4)
    print *,a2
    a2 = 2
  end subroutine
end

  use m

  real :: a1(8)

  a1 = 1

  call sub(a1(::2))

end

对于某些编译器,它会打印 4 次,正如人们所期望的那样,但对于其他编译器或某些编译器参数,它会打印垃圾:

sunf90 intent2.f90 
./a.out 
 5.879759E-39 0.0E+0 0.0E+0 0.0E+0

关于module - Fortran - 模块子例程参数意图混淆 - INOUT 与 OUT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25847014/

相关文章:

linux - 是否可以在 ifort 中启用舍入为零或舍入为负无穷大?

fortran - 现代 Fortran : Calling an ancestor procedure from descendent

用于模块初始化的 Python 钩子(Hook)

module - 每当我在 PyScript 中使用 'import openai' 时,它都会出错

scope - simulink 中的范围删除前几个数据

javascript - 在函数内部调用函数 - 问题 :function not executing

functional-programming - Fortran是纯功能性语言吗?

perl - 如何在具有多个 Perl 版本的 Perl 模块中安装脚本?

magento - 单击下拉选项在管理面板中创建网格 magento 1.7.0.2

javascript - 为什么我的 for 循环在一次迭代后停止?