3

有这个程序:

INTEGER i,k
REAL*8  mp(15,48)
REAL*8  sp(15)
k=0
do i=1,12
   k=k+1
   call Equaltensors(sp,mp(1,k),15)
enddo
end

c=====================

subroutine Equaltensors(tensA,tensB,n)
REAL*8 tensA(n),tensB(n)
INTEGER i
do   i=1,n
     tensB(i)=tensA(i)
enddo
return
end

所以基本上 mp(1,1) 等的值作为 n=15 的向量 tensB(15) 传递给子程序。我不明白的是如何将实数存储在子程序的一维数组中。

4

2 回答 2

6

你的问题的标题有点误导。Fortran 不允许您将标量传递给数组。但它所允许的是将数组的单个元素传递给例程的数组虚拟参数——这在 Fortran 中称为“序列关联”。正如 IanH 和其他人所说,以下元素会自动与虚拟数组的元素相关联,直到被调用例程的实际数组中的最后一个元素。

不过,此功能有一些限制。如果元素是 POINTER 数组,则不能这样做。

回到你的标题,我看到很多程序将常量 3 传递给一个虚拟对象是一个数组的例程。该例程仅使用第一个元素,但这是不合法的,较新的编译器可能会检测到错误并抱怨。一种解决方法是使用数组构造函数将参数转换为数组 - 例如,CALL FOO ([3]),但这仅适用于要读取而不是写入值的情况。

我已经写了一些关于这个一般问题的博客文章 - 请参阅http://software.intel.com/en-us/blogs/2009/03/31/doctor-fortran-in-ive-come-here-for-an -argumenthttp://software.intel.com/en-us/blogs/2009/07/10/doctor-fortran-in-ive-come-here-for-an-argument-side-2

于 2013-08-01T20:46:48.433 回答
4

编辑:根据 IanH 的评论进行了更正,他指出在不对参数传递约定做出假设的情况下保证行为。

这种方法始于早期的 FORTRAN,假设参数作为地址传递,通常称为“引用调用”。scalermp(1,k)的地址是该列第一个元素的地址k。由于 Fortran 以列主要格式 ( http://en.wikipedia.org/wiki/Row-major_order#Column-major_order ) 存储数组,因此第 k 列的 15 个值将在内存中连续。因此,如果被调用的子程序将此地址解释为长度为 15 的一维数组tensB的地址,它将访问第 k 列的元素。

在现代 Fortran 中,可以通过选择具有数组切片的列以更清晰的方式编写参数:mp (:,k)

于 2013-07-26T23:02:28.807 回答