2

在 fortran 中,您可以声明具有任何合适(整数)范围的数组,例如:

real* 8 array(-10:10)

我相信fortran在通过引用传递时,总是会传递array(1)作为引用,但我不确定。

我正在使用fortran 指针,我相信fortran 指向的是“第一个”元素地址,即array(1),而不是array(-10)。但是我不确定。

Fortran 如何处理内存中的负数组索引?它是否定义了实施?

编辑:为了添加更多细节,我通过使用 fortran 指针指向地址将 malloc 块从 C 传递到 fortran,这是通过从 CIe C 中调用 fortran 例程来完成的:

void * pointer = malloc(blockSize*sizeof(double));
fortranpoint_(pointer);

fortran 点例程如下所示:

real*8 :: target block(5, -6:6, 0:0)
real*8 :: pointer array(:,:,:)

entry fortranPoint(block)
array => block
return

问题是,有时当它稍后尝试访问时说:

array(1, -6, 0)

我不确定这是访问块开头的地址还是之前的某个地址。我现在认为这是实现定义的,但想知道每个实现的细节。

4

2 回答 2

1

Fortran 数组参数 ABI 取决于编译器,也许更关键的是,取决于被调用的过程是否具有显式或隐式接口。

对于隐式接口,通常传递第一个元素的地址 [1]。在被调用者中,该过程然后根据数组虚拟参数的声明方式添加一个偏移量。例如,如果数组虚拟参数声明为 somearray(-10:10),则对 somearray(x) 的引用计算为

address_of_first_element_passed_in_to_the_procedure + x + 10

如果过程具有显式接口,则通常传递数组描述符结构而不是第一个元素的地址。在这个结构中,被调用者可以找到每个维度的边界信息,当然还有指向实际数据的指针,允许它计算正确的偏移量,类似于隐式接口的情况。

[1] 注意这是内存中的第一个元素,也就是每个维度的最低索引。不管数组是如何声明的,都不是 somearray(1) 。

要回答您更新的问题,对于 C/Fortran 互操作性,请使用如今广泛使用的 ISO_C_BINDING 功能。这提供了一种在 C 和 Fortran 之间传递信息的标准化方法。

于 2011-08-15T14:19:18.250 回答
0

如果 Fortran 中常规数组的虚拟参数声明为 A(:)(或具有更多维度),则传递 SHAPE,而不是特定的索引范围。因此,该过程将默认为单索引。您可以使用 A(-10:) 或 A(StartIndex:) 过程中的声明来覆盖它,其中 StartIndex 是另一个参数。

Fortran 指针确实包含索引范围,但传递机制将取决于编译器。将其与 C 接口的代码可能取决于操作系统和编译器。正如已经建议的那样,我将使用常规数组和 ISO C 绑定。它比找出编译器传递机制以及标准和可移植的旧方法要容易得多。如果您有大量的现有 Fortran 代码,您可以编写一个“粘合”Fortran 过程,在常规 Fortran 变量声明和 ISO C 绑定名称之间进行映射。虽然它们的类型在形式上会有不同的名称,但实际上,如果您选择正确的 ISO C 类型,它们将是相同的。ISO C 绑定已经存在很多年了——你能升级问题目标平台上的编译器吗?如果没有,我

在其他 Stack Overflow 问题上有 ISO C 绑定使用示例。

如果声明过程的接口以便调用者中的编译器知道它,那么它的接口是显式的。将过程放在模块中并在调用者中“使用”模块的最简单方法。具有显式接口有助于避免错误,因为编译器可以检查调用者和被调用者的参数之间的一致性。它有点像 C 头文件,只是更简单。

于 2011-08-15T15:44:41.653 回答