我正在尝试为'allocate'函数编写一个包装器,即接收数组和维度的函数,分配内存并返回已分配的数组。最重要的是该函数必须使用不同级别的数组。但是我必须在函数接口中明确声明数组的等级,在这种情况下,如果我将某个等级的数组作为参数传递,代码只会编译。例如,此代码无法编译:
module memory_allocator
contains
subroutine memory(array, length)
implicit none
real(8), allocatable, intent(out), dimension(:) :: array
integer, intent(in) :: length
integer :: ierr
print *, "memory: before: ", allocated(array)
allocate(array(length), stat=ierr)
if (ierr /= 0) then
print *, "error allocating memory: ierr=", ierr
end if
print *, "memory: after: ", allocated(array)
end subroutine memory
subroutine freem(array)
implicit none
real(8), allocatable, dimension(:) :: array
print *, "freem: before: ", allocated(array)
deallocate(array)
print *, "freem: after: ", allocated(array)
end subroutine freem
end module memory_allocator
program alloc
use memory_allocator
implicit none
integer, parameter :: n = 3
real(8), allocatable, dimension(:,:,:) :: foo
integer :: i, j, k
print *, "main: before memory: ", allocated(foo)
call memory(foo, n*n*n)
print *, "main: after memory: ", allocated(foo)
do i = 1,n
do j = 1,n
do k = 1, n
foo(i, j, k) = real(i*j*k)
end do
end do
end do
print *, foo
print *, "main: before freem: ", allocated(foo)
call freem(foo)
print *, "main: after freem: ", allocated(foo)
end program alloc
编译错误:
gfortran -o alloc alloc.f90 -std=f2003
alloc.f90:46.14:
call memory(foo, n*n*n)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
alloc.f90:60.13:
call freem(foo)
1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
有没有办法实现这样的包装?
谢谢!
答案 0 :(得分:11)
这可以通过通用接口块完成。您必须为要处理的每个等级创建过程,例如memory_1d,memory_2d,... memory_4d。 (显然有很多剪切和粘贴。)然后你编写一个通用接口块,为所有这些过程提供备用名称内存作为通用过程名称。当您调用内存时,编译器会根据参数的等级区分应调用哪个memory_Xd。你的freem功能也一样。
这就是罪的内在函数长期以来的作用 - 你可以用各种预设的真实参数或复杂的参数来调用sin,并且编译器会用实际的sin函数来调用。在非常古老的FORTRAN中,你必须为不同的sin函数使用不同的名称。现在,现代Fortran可以用自己的例程设置相同的东西。
编辑:添加一个代码示例演示方法&语法:
module double_array_mod
implicit none
interface double_array
module procedure double_vector
module procedure double_array_2D
end interface double_array
private ! hides items not listed on public statement
public :: double_array
contains
subroutine double_vector (vector)
integer, dimension (:), intent (inout) :: vector
vector = 2 * vector
end subroutine double_vector
subroutine double_array_2D (array)
integer, dimension (:,:), intent (inout) :: array
array = 2 * array
end subroutine double_array_2D
end module double_array_mod
program demo_user_generic
use double_array_mod
implicit none
integer, dimension (2) :: A = [1, 2]
integer, dimension (2,2) :: B = reshape ( [11, 12, 13, 14], [2,2] )
integer :: i
write (*, '( / "vector before:", / 2(2X, I3) )' ) A
call double_array (A)
write (*, '( / "vector after:", / 2(2X, I3) )' ) A
write (*, '( / "2D array before:" )' )
do i=1, 2
write (*, '( 2(2X, I3) )' ) B (i, :)
end do
call double_array (B)
write (*, '( / "2D array after:" )' )
do i=1, 2
write (*, '( 2(2X, I3) )' ) B (i, :)
end do
stop
end program demo_user_generic
答案 1 :(得分:1)
subroutine memory(array, length)
第一个虚拟参数 1维数组(real(8), allocatable, intent(out), dimension(:) :: array
)。
使用 3维数组 foo(real(8), allocatable, dimension(:,:,:) :: foo
)从主程序调用此子程序显然是错误的。这就是编译器实际上所说的。
如果你真的需要这样的子程序,为每个不同维度的数组写一对memory
/ freem
子程序 - 一个子程序对用于一维数组,另一个用于二维数组,等等。 / p>
顺便说一句,memory
子程序通常会有所不同,因为为了分配n维数组,你需要将n个范围传递给上面提到的子程序。