我有几个关于INTENT
Fortran 子程序中的变量的问题。例如,几周前,我发布了一个关于不同 Fortran 主题的问题(In Fortran 90, what is a good way to write an array to a text file, row-wise?),其中一个回复包含定义代码tick
和tock
命令。我发现这些对我的代码运行时间很有用。我在下面粘贴tick
并tock
在一个简单的示例中使用它们来计时DO
循环:
MODULE myintenttestsubs
IMPLICIT NONE
CONTAINS
SUBROUTINE tick(t)
INTEGER, INTENT(OUT) :: t
CALL system_clock(t)
END SUBROUTINE tick
! returns time in seconds from now to time described by t
REAL FUNCTION tock(t)
INTEGER, INTENT(IN) :: t
INTEGER :: now, clock_rate
CALL system_clock(now,clock_rate)
tock = real(now - t)/real(clock_rate)
END FUNCTION tock
END MODULE myintenttestsubs
PROGRAM myintenttest
USE myintenttestsubs
IMPLICIT NONE
INTEGER :: myclock, i, j
REAL :: mytime
CALL tick(myclock)
! Print alphabet 100 times
DO i=1,100
DO j=97,122
WRITE(*,"(A)",ADVANCE="NO") ACHAR(j)
END DO
END DO
mytime=tock(myclock)
PRINT *, "Finished in ", mytime, " sec"
END PROGRAM myintenttest
这导致了我的第一个问题INTENT
(下面我的第二个问题是关于未明确指定 INTENT 的子例程或函数参数/变量):
为了启动计时器,我写了
CALL tick(myclock)
,其中myclock
是一个整数。子例程的标题是SUBROUTINE tick(t)
,因此它接受虚拟整数t
作为参数。但是,在子程序内部,t
给出了 INTENT(OUT):INTEGER, INTENT(OUT) :: t
。怎么会这样?我幼稚的假设是 INTENT(OUT) 意味着这个变量的值可能会被修改,并将被导出到子程序之外——而不是读入。但显然t
正在被读入子程序;我将整数传递给myclock
子例程。因此,既然t
被声明为 INTENT(OUT),那它怎么会t
似乎也进来了?我注意到在函数
tock(t)
中,整数变量now
并clock_rate
没有明确给出意图。那么,这些变量的作用域是什么?是否now
只在函数clock_rate
内可见?(有点像 INTENT(NONE) 或 INTENT(LOCAL),虽然没有这样的语法?)而且,虽然这是一个函数,但对子例程是否同样适用?有时,当我编写子例程时,我想声明这样的“临时”变量——这些变量只能在子例程中看到(例如,在分配最终输出之前的步骤中修改输入)。这就是缺乏特定意图的结果吗?
我查看了一个文本(Hahn 的 Fortran 90 文本),在其中,他对参数意图进行了以下简要描述:
论证意图。 可以使用 意图属性指定虚拟参数,即您是否打算将它们用作输入或输出,或两者兼而有之,例如
SUBROUTINE PLUNK(X, Y, Z)
REAL, INTENT(IN) :: X
REAL, INTENT(OUT) :: Y
REAL, INTENT(INOUT) :: Z
...
如果intent 为IN,则虚拟参数的值可能不会在子程序内更改。
如果意图是 OUT,则对应的实际参数必须是变量。一个电话如
CALL PLUNK(A, (B), C)
会产生编译器错误——(B) 是一个表达式,而不是一个变量。
如果意图是 INOUT,则相应的实际参数必须再次是变量。
如果虚拟参数没有意图,则实际参数可能是变量或表达式。
建议为所有虚拟参数指定一个意图。特别是,所有函数参数都应该有意图 IN。也可以在单独的语句中指定意图,例如 INTENT(INOUT) X、Y、Z。
上面的文字似乎甚至没有提到参数/变量范围;似乎主要是在讨论参数/变量值是否可以在子例程或函数内部更改。这是真的吗?如果是这样,关于意图的范围,我可以假设什么?