Fortran数组和子程序(子数组)

cco*_*ook 4 fortran subroutine

我正在阅读Fortran代码,有一点让我感到有些困惑.

比方说,有一个子程序

SUBROUTINE SSUB(X,...)
REAL*8 X(0:N1,1:N2,0:N3-1),...
...
RETURN 
END
Run Code Online (Sandbox Code Playgroud)

在另一个子程序中通过以下方式调用:

CALL SSUB(W(0,1,0,1),...)
Run Code Online (Sandbox Code Playgroud)

其中W是'工作阵列'.看来W中的特定值传递给X,但X的大小为数组.这是怎么回事?

dmc*_*kee 8

这是使子程序在原始数组的(矩形N维)子集上工作的非常常见的习惯用法.

Fortran中的所有参数(至少在Fortran 90之前)都是通过引用传递的,因此实际的数组参数将被解析为内存中的一个位置.为整个数组分配的空间选择一个位置,子程序仅操作数组的一部分.

最大的问题:您必须了解数组在内存中的布局以及Fortran的数组索引方案的工作原理.Fortran使用列主要数组排序,这与c相反.考虑一个大小为5x5的数组(并且从0开始指向两个方向,以便与c进行比较更容易).在两种语言中,0,0是内存中的第一个元素.在c中,内存中的下一个元素是[0][1]在Fortran中(1,0).这会影响您在选择子空间时删除哪些索引:如果原始数组是A(i,j,k,l),并且子例程在三维子空间上工作(如示例所示),则在c中可以使用Aprime[i=constant][j][k][l],但是在Fortran中的作品Aprime(i,j,k,l=constant).

另一个风险是环绕.子例程中(子)数组的维度必须与调用例程中的维度匹配,否则会发生奇怪的奇怪事情(想一想).因此,如果A被声明为size(0:4,0:5,0:6,0:7),并且我们使用element调用A(0,1,0,1),则接收例程可以自由地启动每个维度的索引,但是必须制作尺寸(4,5,6)或其他; 但这意味着j方向的最后一个元素实际上是环绕的!要做的就是使用最后一个元素.确保发生这种情况是程序员的工作,并且是一个痛苦的屁股.照顾自己.很多照顾.