FORTRAN 77中子程序参数的范围
我有一个子例程,它声明FORTRAN 77中子程序参数的范围,fortran,fortran77,Fortran,Fortran77,我有一个子例程,它声明I,并将其传递给其他小型子例程。在这些小型子例程中,声明了具有相同名称的其他变量,即i,并在内部使用。一旦退出小型子例程,人们会期望得到与最初传递的i值相同的值,但这不是真实情况,并且i包含小型子例程中分配的最后一个参数的值。下面是一个简单的例子: subroutine smallSub1(i) integer i,start,end start=i end = start +10 do i=start, end write(*,*) i enddo en
I
,并将其传递给其他小型子例程。在这些小型子例程中,声明了具有相同名称的其他变量,即i
,并在内部使用。一旦退出小型子例程,人们会期望得到与最初传递的i
值相同的值,但这不是真实情况,并且i
包含小型子例程中分配的最后一个参数的值。下面是一个简单的例子:
subroutine smallSub1(i)
integer i,start,end
start=i
end = start +10
do i=start, end
write(*,*) i
enddo
end subroutine smallSub1
subroutine caller
integer i
i = 1
call smallSub1(i)
write(*,*) i
end subroutine caller
我的问题是,如何在F77中避免这种行为
我在这里关心的是:考虑这样一种情况,子例程是一个黑匣子,您只需要传递一个整数,但不希望该整数值从smallSub1
子例程更改。变量start
和end
将取决于i
的值,但是它们不应替换i
的原始值,而不是从smallSub1
中删除
Fortran通过引用传递大多数参数
因此,如果不想更改变量,请不要在子例程中更改它。您可以将变量smallSub1(i)重命名为smallSub1(j)
您不想更改整个函数。来自
Fortran通过引用传递大多数参数
因此,如果不想更改变量,请不要在子例程中更改它。您可以将变量smallSub1(i)重命名为smallSub1(j)
您不想更改整个函数。在给定的代码示例中,有两个变量
i
:每个子例程中一个。在子程序caller
中,i
是一个局部变量,在子程序smallSub1
中,它是一个伪参数
当您有调用smallSub1(i)
时,您通过参数关联将两个i
变量彼此关联起来。在这种简单的情况下,smallSub1
中对i
的任何更改都会影响调用者中的i
。这里有参数关联的工作原理
传统上,人们确实有一个黑匣子,在这个黑匣子中,一个参数在不需要的时候在子例程中被改变。例如,将其用作工作空间的位置。在这种情况下,一个人会做这样的事情
inew = i
call smallSub1(inew)
... continue using i
但是,在这种情况下,可以很容易地(我想)更改子例程。引入一个额外的局部变量:
subroutine smallSub1(i)
integer i ! Dummy argument - we don't want to change it
integer start,end
integer j ! Local variable - we're quite free to change it
! In general, we'd have j=i at the start and use that instead
start=i
end = start +10
do j=start, end
write(*,*) j
enddo
end subroutine smallSub1
在现代Fortran中,甚至有value
属性,该属性可以应用于伪参数,允许用户在不影响实际参数的情况下更改它。在给定的代码示例中,有两个变量i
:每个子例程中有一个。在子程序caller
中,i
是一个局部变量,在子程序smallSub1
中,它是一个伪参数
当您有调用smallSub1(i)
时,您通过参数关联将两个i
变量彼此关联起来。在这种简单的情况下,smallSub1
中对i
的任何更改都会影响调用者中的i
。这里有参数关联的工作原理
传统上,人们确实有一个黑匣子,在这个黑匣子中,一个参数在不需要的时候在子例程中被改变。例如,将其用作工作空间的位置。在这种情况下,一个人会做这样的事情
inew = i
call smallSub1(inew)
... continue using i
但是,在这种情况下,可以很容易地(我想)更改子例程。引入一个额外的局部变量:
subroutine smallSub1(i)
integer i ! Dummy argument - we don't want to change it
integer start,end
integer j ! Local variable - we're quite free to change it
! In general, we'd have j=i at the start and use that instead
start=i
end = start +10
do j=start, end
write(*,*) j
enddo
end subroutine smallSub1
而现代Fortran甚至有value
属性,它可以应用于伪参数,允许用户在不影响实际参数的情况下对其进行更改。如另一个答案中所述,Fortran通常通过引用进行传递,当这不可能时,它会执行诸如“复制入/复制出”之类的操作。正如其他人在评论中简洁地说的那样,如果你不想更改i
,那么就不要更改i
在子例程smallSub1
中,i
被用作循环迭代变量,并且您不希望其值更改对调用方可见。更改i
的原因对调用方可见,因为i
不是局部变量,而是伪参数。解决方案是使用不同的名称调用循环变量和伪参数。其中一个解决办法是:
subroutine smallSub1(i_from_caller)
integer i,i_from_caller,start,end
start = i_from_caller
end = start +10
do i=start, end
write (*,*) i
end do
end subroutine smallSub1
在这种情况下,伪参数已从调用方重命名为i\u,用于初始化start
。现在循环变量i
确实是子例程的本地变量(因为它不再是伪参数的名称),在这里更改i
不会在调用者中更改i
为了帮助避免这种行为,您可以向编译器提示伪参数用于输入、输出或两者。如果您在原始示例中将i
声明为integer,intent(in)::i
insmallSub1
,编译器会抱怨:
do i=start, end
1
Error: Dummy argument ‘i’ with INTENT(IN) in variable definition context (iterator variable) at (1)
使您意识到您正在对伪参数进行不必要的更改。如另一个答案中所述,Fortran通常通过引用进行传递,当这不可能时,它会执行诸如复制入/复制出之类的操作。正如其他人在评论中简洁地说的那样,如果你不想更改i
,那么就不要更改i
在子例程smallSub1
中,i
被用作循环迭代变量,并且您不希望其值更改对调用方可见。更改i
的原因对调用方可见,因为i
不是局部变量,而是伪参数。解决方案是使用不同的名称调用循环变量和伪参数。其中一个解决办法是:
subroutine smallSub1(i_from_caller)
integer i,i_from_caller,start,end
start = i_from_caller
end = start +10
do i=start, end
write (*,*) i
end do
end subroutine smallSub1
在这种情况下,伪参数已从调用方重命名为i\u,用于初始化start
。现在,循环变量i
确实是子循环的局部变量