分配数组和指针的等价

分配数组和指针的等价

本文介绍了FORTRAN:分配数组和指针的等价的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个分配的数组A Fortran程序如下:

I have a fortran program with an allocatable array A as follows:

real, dimension(:,:) allocatable :: A
...
allocate(A(x0:x1;y0:y1))

这阵最终作为参数传递给一个子程序,看起来像通过

This array is eventually passed as argument to a subroutine which looks like

subroutine my_subroutine(arr)
   real, dimension(x0:x1,y0:y1) :: arr
   ...
end subroutine my_subroutine

我想通过一个自定义的内存分配函数my_alloc在C库中实现,以取代Fortran语言的分配的声明。目前,我改变了最初的code样品为:

I wanted to replace the "allocate" statement of Fortran by a custom memory allocation function "my_alloc" implemented in a C library. Currently I changed the first code sample into:

type(c_ptr) :: cptr
real, pointer, dimension(:,:) :: A
...
cptr = my_alloc(...)
call c_f_pointer(cptr,A,[x1-x0+1,y1-y0+1])

这工作得很好,除了通过指定,而不是在C_F_POINTER功能下/上限范围,我失去了原来的形状的数组(X0:Y1:X1,Y0)。但是,这不是一个大问题:指针路人的子程序的说法,子程序期待一个数组,并考虑指针数组,用正确的边界

This works fine, except that by specifying extents instead of lower/upper bounds in the c_f_pointer function, I lose the original shape (x0:x1,y0:y1) of the array. But this is not a big problem: the pointer is passer as argument of the subroutine, the subroutine expect an array and consider the pointer as an array, with the proper bounds.

我的真正的问题是:当我想也改写子程序的code有一个指针,而不是数组

My real problem is: when I want to also rewrite the subroutine's code to have a pointer instead of an array.

subroutine my_subroutine(arr)
   real, pointer, dimension(x0:x1,y0:y1) :: arr
   ...
end subroutine my_subroutine

上面的code不工作; gfortran说:数组指针'改编'在(1)必须有延迟的外形

The code above doesn't work; gfortran says: Array pointer 'arr' at (1) must have a deferred shape

以下code可以编译:

the following code can be compiled:

subroutine my_subroutine(arr)
   real, pointer, dimension(:,:) :: arr
   ...
end subroutine my_subroutine

但是,当我试图执行一个循环从X0到X1和从Y0到Y1它不提供的范围和程序崩溃。

But it doesn't provide the bounds and the program crashes when I try to perform a loop from x0 to x1 and from y0 to y1.

我该如何处理这种情况?在子程序,我需要FORTRAN知道ARR是一个指针形数组(X0:X1,Y0,Y1)

How can I handle this case? Within the subroutine, I need fortran to know that arr is a pointer to an array shaped (x0:x1,y0;y1).

感谢

推荐答案

是的,这是因为C_F_POINTER的限制的问题。正如你所发现的内在C_F_POINTER只支持范围从索引1.人们经常指出,Fortran语言是一个索引语言,但这不是真的。一个索引仅默认和Fortran长期以来一直支持声明的约束,程序员想要的任何起点。所以这是一种倒退的C_F_POINTER强迫你使用一个索引。但与2003年的Fortran有修补程序:指针边界重新映射:

Yes, this was a problem because of the limitation of c_f_pointer. As you have found the intrinsic c_f_pointer only supports bounds starting at index 1. People frequently state that Fortran is a one-indexed language but this not true. One indexing is only the default and Fortran has long supported declaring any starting bound that the programmer wants. So it was a step backwards that c_f_pointer forced you to use one indexing. But with Fortran 2003 there is a fix: pointer bounds remapping:

arr (0:n-1) => arr

而不是1:N,或任何你想

instead of 1:n, or whatever you wish.

然后通过数组的子程序,它会收到预期的范围。

Then pass the array to the subroutine and it will receive the intended bounds.

编辑:改善显示allocatables和指针之间的区别演示程序。指针经过阵列的边界。一个规则的数组传递的形状......你可以宣布第一个维度的子程序,如果你愿意,并让形状控制第二。

improve demo program showing the difference between allocatables and pointers. The pointer passes the bounds of the array. A regular array passes the shape ... you can declare the first dimension in a subroutine, if you wish, and let the shape control the second.

module mysubs

implicit none

contains

subroutine testsub ( ptr, alloc, start, array )

   real, pointer, dimension (:) :: ptr
   real, dimension (:), intent (in) :: alloc
   integer, intent (in) :: start
   real, dimension (start:), intent (in) :: array

   write (*, *) "pointer in sub:", lbound (ptr, 1), ubound (ptr, 1)
   write (*, *) ptr

   write (*, *) "1st array in sub:", lbound (alloc, 1), ubound (alloc, 1)
   write (*, *) alloc

   write (*, *) "2nd array in sub:", lbound (array, 1), ubound (array, 1)
   write (*, *) array

   return

end subroutine testsub

end module mysubs


program test_ptr_assignment

use mysubs

implicit none

real, pointer, dimension(:) :: test
real, allocatable, dimension(:) :: alloc1, alloc2
real, allocatable, dimension(:) :: alloc1B, alloc2B

allocate ( test (1:5), alloc1 (1:5), alloc1B (1:5) )
test = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]
alloc1 = test
alloc1B = test

write (*, *) "A:", lbound (test, 1), ubound (test, 1)
write (*, *) test

call testsub (test, alloc1, 1, alloc1B )

test (0:4) => test
allocate ( alloc2 (0:4), alloc2B (0:4) )
alloc2 = test
alloc2B = test

write (*, *)
write (*, *) "B:", lbound (test, 1), ubound (test, 1)
write (*, *) test

call testsub (test, alloc2, 0, alloc2B)

stop

end program test_ptr_assignment

这篇关于FORTRAN:分配数组和指针的等价的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 18:32