tsumey tsumey - 3 months ago 25
C Question

How can I pass a dynamic allocated arrays to subroutines

I need to get rid of some libraries that a Fortran program uses, so I have to create all the subroutines in the Library used in the program.

One of those subroutines is memory allocation which is done by C language.

I created my own subroutine for the allocation

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


but I need to keep the declaration of the array which done like this
integer alist(1)
without the attribute
allocatable
.

example

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

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


Is there a way I can make my array
allocatable
after the declaration ?
I'm thinking of making it
allocatable
(after declaration) Inside the subroutine allocating memory so that in don't have to change the declaration in my old program.

Answer

is there a way i can make my array allocatable after the declaration ? i'm thinking of making it allocatable (after declaration) Inside the subroutine allocating memory so that in don't have to change the declaration in my old program.

No.

The error message is very explicit. You can't pass a non allocatable array as argument to a function that is expecting an allocatable array.

The following declaration:

integer alist(1)

Is creating an array of 1 dimension of size 1.

If you want your arrays to be allocated dynamic, you must change them to allocatable or use pointers.

EDIT

As from here: http://web.stanford.edu/class/me200c/tutorial_77/12_arrays2.html

Most programmers prefer to use the asterisk notation to emphasize that the "real array length" is unknown. Some old Fortran 77 programs may declare variable length arrays like this:

  real x(1), y(1)

This is legal syntax even if the array lengths are greater than one! But this is poor programming style and is strongly discouraged.

P.S. This notation is used INSIDE subroutines to define variable length array arguments.

EDIT 2

The following code, based on yours, demonstrate the use of 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

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 ARRAY_ALLOCATE(alist,5,3,1)
if (allocated(alist)) then
    print *, "is allocated"
else
    print *, "is not allocated"
endif    
print *, alist
CALL ARRAY_DEALLOCATE(alist)
if (allocated(alist)) then
    print *, "is allocated"
else
    print *, "is not allocated"
endif
end program Console1

The expected result would be something like this:

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