Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory 负数组索引和内存中的位置(指向)_Memory_Fortran_Fortran Iso C Binding - Fatal编程技术网

Memory 负数组索引和内存中的位置(指向)

Memory 负数组索引和内存中的位置(指向),memory,fortran,fortran-iso-c-binding,Memory,Fortran,Fortran Iso C Binding,在fortran中,可以声明具有任何合适(整数)范围的数组,例如: real* 8 array(-10:10) 我相信fortran在通过引用传递时,将始终传递数组(1)作为引用,但我不确定 我使用的是fortran指针,我相信fortran指向的是“第一”元素地址,即数组(1),而不是数组(-10)。但是我不确定 Fortran如何处理内存中的负数组索引?它是否定义了实现 编辑:为了增加一点细节,我使用fortran指针将一个malloc'd块从C传递到fortran,指向地址,这是通过从C

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

real* 8 array(-10:10)
我相信fortran在通过引用传递时,将始终传递数组(1)作为引用,但我不确定

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

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

编辑:为了增加一点细节,我使用fortran指针将一个malloc'd块从C传递到fortran,指向地址,这是通过从C中调用fortran例程来完成的。例如,C:

void * pointer = malloc(blockSize*sizeof(double));
fortranpoint_(pointer);
fortran point例程如下所示:

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

entry fortranPoint(block)
array => block
return
问题是,有时当它稍后尝试访问时,会说:

array(1, -6, 0)

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

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_绑定功能。这提供了一种在C和Fortran之间传递信息的标准化方法。

如果Fortran中规则数组的伪参数声明为(:)(或具有更多维度),则传递的是形状,而不是特定的索引范围。因此,该过程将默认为一个索引。您可以在a(-10:)或a(StartIndex:)的过程中使用声明来重写此函数,其中StartIndex是另一个参数

Fortran指针确实包含索引范围,但传递机制将依赖于编译器。将其连接到C的代码可能依赖于操作系统和编译器。如前所述,我将使用常规数组和ISO C绑定。它比旧的方法更容易弄清楚编译器的传递机制以及标准和可移植性。如果您有一个大型的现有Fortran代码,那么可以编写一个“粘合”Fortran过程,在常规Fortran变量声明和ISO C绑定名称之间进行映射。虽然它们的类型在形式上有不同的名称,但实际上,如果选择正确的ISO C类型,它们将是相同的。ISO C绑定已经提供了很多年了——您能在有问题的目标平台上升级编译器吗?如果不是,我将使用常规Fortran数组,在C端使用零索引,或者显式地将所需索引作为参数传递

在其他堆栈溢出问题上也有使用ISO C绑定的例子


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

使用ISO_C_绑定是否需要我更改Fortran中使用的数据类型?我查了一下,说不出来。我是一个C程序员,必须使用一些Fortran语言,我不能像更改数据类型那样大规模地编辑它们。嗯,你需要确保类型和类型匹配,是的。但我不认为这是一个特别大的问题。例如,如果C代码使用DOUBLE,那么ISO_C_绑定内容应该使用REAL(kind=C_DOUBLE),然后您需要确保REAL(kind=C_DOUBLE)与您绑定到使用的Fortran过程的类型相同。请注意,这些类型只是整数参数;在今天的大多数编译器上,KIND(1.0d0)=C\u DOUBLE==selected\u real\u KIND(15)==8,所以很可能您可以使用。我的一个目标平台上不存在ISO\u C\u绑定,因此很遗憾,我无法编写涉及它的代码。你知道我在哪里可以找到详细说明哪个编译器处理它的数组的信息吗?与此同时,我以前从未听说过“隐式”和“显式”接口这两个术语。它们是什么意思?谢谢