Fortran是否通过函数和子例程调用保留内部变量的值?

EMi*_*ler 9 fortran scope function subroutine

经过多次痛苦的调试后,我相信我已经找到了Fortran的一个独特属性,我想在stackoverflow验证这里.

我一直注意到的是,至少,内部逻辑变量的值在函数或子程序调用中保留.

这是一些示例代码来说明我的观点:

PROGRAM function_variable_preserve
IMPLICIT NONE

CHARACTER(len=8) :: func_negative_or_not ! Declares function name
INTEGER :: input
CHARACTER(len=8) :: output

input = -9

output = func_negative_or_not(input)
WRITE(*,10) input, " is ", output
10 FORMAT("FUNCTION: ", I2, 2A)

CALL sub_negative_or_not(input, output)
WRITE(*,20) input, " is ", output
20 FORMAT("SUBROUTINE: ", I2, 2A)

WRITE(*,*) 'Expected negative.'


input = 7
output = func_negative_or_not(output)
WRITE(*,10) input, " is ", output

CALL sub_negative_or_not(input, output)
WRITE(*,20) input, " is ", output

WRITE(*,*) 'Expected positive.'

END PROGRAM function_variable_preserve

CHARACTER(len=*) FUNCTION func_negative_or_not(input)
IMPLICIT NONE

INTEGER, INTENT(IN) :: input
LOGICAL :: negative = .FALSE.

IF (input < 0) THEN
    negative = .TRUE.
END IF

IF (negative) THEN
    func_negative_or_not = 'negative'
ELSE 
    func_negative_or_not = 'positive'
END IF

END FUNCTION func_negative_or_not

SUBROUTINE sub_negative_or_not(input, output)
IMPLICIT NONE

INTEGER, INTENT(IN) :: input
CHARACTER(len=*), INTENT(OUT) :: output
LOGICAL :: negative = .FALSE.

IF (input < 0) THEN
    negative = .TRUE.
END IF

IF (negative) THEN
    output = 'negative'
ELSE 
    output = 'positive'
END IF

END SUBROUTINE sub_negative_or_not
Run Code Online (Sandbox Code Playgroud)

这是输出:

FUNCTION: -9 is negative
SUBROUTINE: -9 is negative
 Expected negative.
FUNCTION:  7 is negative
SUBROUTINE:  7 is negative
 Expected positive.
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,一旦函数或子例程被调用一次,逻辑变量negative(如果切换到.TRUE.)仍然如此,尽管在类型声明语句中初始化为negativeto .FALSE..

当然,我可以通过添加一个负数= .FALSE来纠正这个问题.在我的函数和子程序中声明变量之后.

但是,对我来说这似乎很奇怪,这是必要的.

为了便携性和代码可重用性,每次调用子例程或函数时,语言(或编译器)是否都不需要重新初始化所有内部变量?

Hig*_*ark 13

回答你的问题:是的Fortran确实通过函数和子程序调用来保留内部变量的值.

在某些条件下......

如果使用SAVE属性声明内部变量,则将其值从一次调用保存到下一次.当然,这在某些情况下是有用的.

但是,您的问题是在首次了解Fortran的一个陷阱时的常见反应:如果您在其声明中初始化内部变量,那么它会自动获取SAVE属性.您已在子例程中完成了这一操作.这符合标准.如果您不希望发生这种情况,请不要在声明中初始化.

这是该语言(一些)新手的惊喜和抱怨的原因.但无论他们多么努力地抱怨它都不会改变所以你只需要(a)知道它并且(b)计划意识到它.