【问题标题】:Fortran - Module Subroutine Argument Intent Confusion- INOUT vs OUTFortran - 模块子程序参数意图混淆 - INOUT vs OUT
【发布时间】:2014-09-15 11:27:10
【问题描述】:

假设有一个向量:

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(IN)吗?
  • 糟糕,感谢您指出这一点 - 已修复

标签: module scope fortran subroutine


【解决方案1】:

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

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

  rho(::2)

编译器很可能会创建一个副本,它被传递了,你很可能会遇到问题,因为该数组可能包含带有intent(out) 的垃圾。

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

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

关于范围:

这里说作用域是不太对的,原来rho肯定不在子程序作用域,只有dummy argument在。重用同名可能会令人困惑。想象一下,它们实际上在程序中称为rho1,在子例程中称为rho2。那么很明显rho1不在子程序范围内,而rho2在。

现在,rho2 不能保证在 intent(out) 的子例程开始时与 rho1 具有相同的值,但可以保证与 intent(inout) 具有相同的值。原因是参数传递可以使用copy-in和copy-out实现,intent(out)可以省略copy-in。

考虑这段代码:

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 次 1,正如人们所期望的那样,但使​​用其他编译器或使用某些编译器参数,它会打印垃圾:

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

【讨论】:

  • 感谢您的回答(并指出我在问题最后一句中的错字)。那么,如果 INTENT 被声明为 OUT,您能否澄清最初声明的 rho 通常是否超出模块的范围?您是说由于显式形状数组的实现方式而将其纳入范围?
  • 无论intent 是什么,最初声明的rho 在模块过程的范围内从不。然而,与之相关的内存也与模块过程中的虚拟参数相关联。
猜你喜欢
  • 2011-02-22
  • 2011-07-29
  • 1970-01-01
  • 2019-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
相关资源
最近更新 更多