我知道(至少在某一点上),由于别名,以下内容在 Fortran 中是无效的
program main
integer :: x, y
! compilers assume a and b to be distinct
y = f(x, x)
contains
integer function f(a, b) result(c)
integer, intent(in out) :: a, b
a = 1
b = 2
c = a ! compiler can optimize to c = 1
end function
end program main
但是以下内容有效吗?
program main
integer :: x(3)
x = [1, 2, 3]
x = square_me(x)
contains
function square_me(a) result(squared)
integer, intent(in out) :: a(3)
integer :: squared(3)
integer :: i
squared = a ** 2
a(1) = 0 ! nasty side-effect
end function
end program main
它可以在 gfortran 中运行,但我不确定它是否符合标准。
我知道函数中的副作用不是一个好主意。我正在处理超过 100k 行的遗留代码,这些代码喜欢使用 C 风格的整数代码返回函数并修改参数,所以这个问题专门与标准有关。
主程序均无效。
Fortran 中所谓的别名规则通常是指在过程执行期间应用于实体的那些限制。然而,在赋值语句中,在影响左侧之前,会先完全执行右侧的求值。
相反,破坏第二个主程序的是对函数副作用的限制。
副作用受到限制(F2018,10.1.4),除非在某些情况下不适用:
如果函数引用导致函数实际参数的定义或取消定义,则该参数或任何关联实体不得出现在同一语句的其他位置
对
a(1)
的赋值会导致实际参数 x
的定义,因此 x
可能不会出现在赋值语句的其他位置(包括左侧)。
函数中的副作用还有其他几个(也许令人惊讶的)限制。我们只想说:如果可以的话,请避免函数中的副作用,除非您真的了解规则,并且可以确保使用您的函数的每个人也确实了解规则。