首页 文章

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

提问于
浏览
4

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

比方说,有一个子程序

SUBROUTINE SSUB(X,...)
REAL*8 X(0:N1,1:N2,0:N3-1),...
...
RETURN 
END

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

CALL SSUB(W(0,1,0,1),...)

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

3 回答

  • 2

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

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

    Biggest issue: 你必须be aware of how the array is laid out in memory以及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),并且我们使用元素 A(0,1,0,1) 调用,则接收例程可以自由地启动每个维度的索引,但是它们喜欢它,但是必须制作尺寸 (4,5,6) 或者;但这意味着j方向的最后一个元素实际上是环绕的!要做的就是不使用最后一个元素 . 确保发生这种情况是程序员的工作,并且是一个痛苦的屁股 . 照顾自己 . 很多照顾 .

  • 2

    在fortran变量中通过地址传递 . 所以 W(0,1,0,1) 是 Value 和地址 . 所以基本上你从 W(0,1,0,1) 开始传递子阵列 .

  • 7

    这称为“序列关联” . 在这种情况下,似乎是缩放器,数组的元素(调用者中的实际参数)与数组(隐式第一个元素),子例程中的伪参数相关联 . 此后,阵列的元素通过存储顺序关联,称为“序列” . 这是在Fortran 77及更早版本中出于各种原因完成的,这显然是针对工作区数组 - 也许程序员正在进行自己的内存管理 . 为了向后兼容性,这在Fortran> = 90中保留,但IMO不属于新代码 .

相关问题