如何将动态分配的数组传递给子例程

时间:2016-08-19 08:39:41

标签: c arrays fortran

我需要摆脱Fortran程序使用的一些库,所以我必须在程序中使用的库中创建所有子程序。

其中一个子程序是内存分配,由C语言完成。

我为分配创建了自己的子程序

MODULE ARRAY_ALLOCATION
  CONTAINS
     SUBROUTINE ARRAY_ALLOCATE (ARR, ARR_SIZE, ARR_IDX, CODE_RET)
            ! DECLARE AN ALLOCATABLE PARAMETER
            INTEGER, ALLOCATABLE, INTENT (INOUT) :: ARR(:)
            INTEGER, INTENT (IN) :: ARR_SIZE,ARR_IDX,CODE_RET
            INTEGER :: IDX_END
            IDX_END = ARR_IDX + ARR_SIZE -1
            ALLOCATE (ARR(ARR_IDX:IDX_END))
            RETURN
     END SUBROUTINE ARRAY_ALLOCATE

     SUBROUTINE ARRAY_DEALLOCATE (ARR)
            INTEGER, ALLOCATABLE, INTENT (INOUT) :: ARR(:)
            DEALLOCATE (ARR)
            RETURN
       END SUBROUTINE ARRAY_DEALLOCATE

END MODULE 

但是我需要保留数组的声明,就像integer alist(1)一样,没有属性allocatable

例如

    program test1

USE ARRAY_ALLOCATION
implicit none

integer alist(1)

call ARRAY_ALLOCATE(alist,5,3,1)
CALL Test(ALIST)
CALL ARRAY_DEALLOCATE(alist)

错误

error #7976: An allocatable dummy argument may only be argument associated with an allocatable actual argument

有没有办法在声明后制作我的数组allocatable? 我正在考虑将它allocatable(在声明之后)在子程序内部分配内存,这样就不必在我的旧程序中更改声明。

2 个答案:

答案 0 :(得分:1)

  

有没有办法让我的数组在声明后可以分配?我正在考虑将其分配(在声明之后)在子程序内部分配内存,这样就不必在旧程序中更改声明。

没有

错误消息非常明确。您不能将不可分配的数组作为参数传递给期望可分配数组的函数。

以下声明:

integer alist(1)

正在创建一个1维大小的数组。

如果希望为数组分配动态,则必须将它们更改为可分配或使用指针。

编辑

从此处开始:http://web.stanford.edu/class/me200c/tutorial_77/12_arrays2.html

  

大多数程序员喜欢使用星号表示法强调"实际数组长度"不明。一些旧的Fortran 77程序可能会声明这样的可变长度数组:

  real x(1), y(1)
  

即使数组长度大于1,这也是合法的语法!    但这是糟糕的编程风格,并且强烈反对。

P.S。这种表示法用于INSIDE子程序来定义变长数组参数。

编辑2

以下代码基于您的代码,演示了如何使用allocatable。

MODULE ARRAY_ALLOCATION
CONTAINS
 SUBROUTINE ARRAY_ALLOCATE (ARR, ARR_SIZE, ARR_IDX, CODE_RET)
        ! DECLARE AN ALLOCATABLE PARAMETER
        INTEGER, ALLOCATABLE, INTENT (INOUT) :: ARR(:)
        INTEGER, INTENT (IN) :: ARR_SIZE,ARR_IDX,CODE_RET
        INTEGER :: IDX_END
        IDX_END = ARR_IDX + ARR_SIZE -1
        ALLOCATE (ARR(ARR_IDX:IDX_END))
        ARR = 1
        RETURN
 END SUBROUTINE ARRAY_ALLOCATE

 SUBROUTINE ARRAY_DEALLOCATE (ARR)
        INTEGER, ALLOCATABLE, INTENT (INOUT) :: ARR(:)
        DEALLOCATE (ARR)
        RETURN
   END SUBROUTINE ARRAY_DEALLOCATE

subroutine Create (arr)
    INTEGER, ALLOCATABLE, INTENT (INOUT) :: ARR(:)
    call ARRAY_ALLOCATE(arr,5,3,1)
end subroutine Create

subroutine Destroy (arr)
    INTEGER, ALLOCATABLE, INTENT (INOUT) :: ARR(:)
    CALL ARRAY_DEALLOCATE(arr)
end subroutine Destroy 

END MODULE 

program Console1

USE ARRAY_ALLOCATION
implicit none

integer, allocatable :: alist(:)
if (allocated(alist)) then
    print *, "is allocated"
else
    print *, "is not allocated"
endif
call Create(alist)
if (allocated(alist)) then
    print *, "is allocated"
else
    print *, "is not allocated"
endif    
print *, alist
CALL Destroy(alist)
if (allocated(alist)) then
    print *, "is allocated"
else
    print *, "is not allocated"
endif
end program Console1

预期结果将是这样的:

is not allocated
is allocated
          1           1           1           1           1
is not allocated

编辑3

关于可分配数组,可以在此处找到有关为什么有人想要解除分配的简单解释https://www.phy.ornl.gov/csep/pl/node17.html

  

可分配数组是显式声明为ALLOCATABLE的数组。可分配数组可以是过程的本地数据,也可以放在模块中,并且对应用程序的所有过程都是有效的。使用ALLOCATE语句显式分配可分配数组,并使用DEALLOCATE语句显式释放,或者如果它是未指定SAVE的本地数组,则在退出过程时自动释放。 (如果已指定SAVE,则本地可分配数组可以从过程的一次执行持续到下一次 - 它们必须使用DEALLOCATE语句显式释放。)全局可分配数组一直存在,直到它被显式释放,这可能发生在过程中不同于分配它的那个。

可以看出,有些情况下必须手动完成释放可分配数组。

答案 1 :(得分:0)

您可能不想删除库,而是让代码在其中工作。

通常它是这样的: 在图书馆......

MODULE A_Style   !(_*_)
IMPLICIT NONE
PUBLIC: Aye

  CONTAINS
  SUBROUTINE Aye(A)
  REAL, DIMENSION(:), ALLOCATABLE, INTENT(INOUT) :: A
  !...
  IF(ALLOCATED(A)) THEN
    WRITE(*,*)' I see A as A(',LBOUND(A,1),':',UBOUND(A,1),')'
  ELSE
    WRITE(*,*)' I see A as "UNALLOCATED"'
  ENDIF
  !...
  RETURN
  END SUBROUTINE Aye

  SUBROUTINE MakeAye(A, SizeA)
  REAL, DIMENSION(:), ALLOCATABLE, INTENT(INOUT) :: A
  !...
  IF(ALLOCATED(A)A) DEALLOCATE(A)
  ALLOCATE(A(SizeA))
  !...
  RETURN
  END SUBROUTINE MakeAye

END MODULE A_Style

使用图书馆:

PROGRAM TestA
USE A_Style  !(_*_)
IMPLICIT NONE
REAL, DIMENSION(:), ALLOCATABLE :: A
INTEGER                         :: Size_A = 100
...
CALL Aye(A)
ALLOCATE(A(Size_A))
CALL Aye(A)
...
IF(ALLOCATED(A)) DEALLOCATE(A)
END PROGRAM TestA

有时,有趣的是,子程序需要在模块中才能看到BOUNDS。然后,INTENT(OUT)将不会出现,因此需要使用(INOUT)或(IN)。