Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29590 Discussions

Allocatable array and subprogram call question

anthonyrichards
New Contributor III
2,063 Views
I need to recover a 2-Dimensional array (one fixed dimension=2, the other dimension variable) of integer data from a subprogram, but at the time of calling the subprogram I do not know how large an array will be generated by the subprogram.
My first instinct is to define an allocatable array and supply it as an argument, but I note from the documentation that an allocatable array cannot be used as a dummy argument, but only as a real argument.

Is there any solution? I know what the absolute maximum amount of integer data can be generated, but it is so large that it would be very inefficient to specify a fixed array of such a size.
0 Kudos
7 Replies
Steven_L_Intel1
Employee
2,063 Views
An allocatable array can be used as a dummy argument and you can allocate it to the desired dimension in the called subroutine. Which documentation told you otherwise? Please note that an explicit interface is required to be visible to the caller, and of course you need to pass an allocatable.
0 Kudos
Les_Neilson
Valued Contributor II
2,063 Views
I just tried it and it works fine.

[fortran] program arraytest implicit none integer, allocatable :: ar1(:,:) ! ---------------------------------------- integer :: k integer :: i interface subroutine mysub(l,m) implicit none integer l integer, allocatable :: m(:,:) end subroutine mysub end interface call mysub(k, ar1) write(*,*) 'k = ',k do i = 1,k write(*,*) 'i = ',i,' ar1(1,i) = ',ar1(1,i) end do do i = 1,k write(*,*) 'i = ',i,' ar1(2,i) = ',ar1(2,i) end do end[/fortran]

and the array is allocated in mysub

[fortran] subroutine mysub(j, inar) implicit none integer :: j integer, allocatable :: inar(:,:) integer :: ierr integer :: i allocate(inar(2,20),stat=ierr) j = 20 do i = 1,j inar(1,i) = i*2 inar(2,i) = i*3 enddo end subroutine [/fortran]
Les
0 Kudos
anthonyrichards
New Contributor III
2,063 Views
CVF help said this:
"

Array Arguments

Arrays are sequences of elements. Each element of an actual array is associated with the element of the dummy array that has the same position in array element order.

If the dummy argument is an explicit-shape or assumed-size array, the size of the dummy argument array must not exceed the size of the actual argument array.

The type and kind parameters of an explicit-shape or assumed-size dummy argument must match the type and kind parameters of the actual argument, but their ranks need not match.

If the dummy argument is an assumed-shape array, the size of the dummy argument array is equal to the size of the actual argument array. The associated actual argument must not be an assumed-size array or a scalar (including a designator for an array element or an array element substring).

If the actual argument is an array section with a vector subscript, the associated dummy argument must not be defined.

The declaration of an array used as a dummy argument can specify the lower bound of the array.

Although most types of arrays can be used as dummy arguments, allocatable arrays cannot be dummy arguments. Allocatable arrays can be used as actual arguments.

Dummy argument arrays declared as assumed-shape, deferred-shape, or pointer arrays require an explicit interface visible to the caller."

Within the parameters of these statements, what is a 'dummy' as opposed to an 'actual' argument?

0 Kudos
anthonyrichards
New Contributor III
2,063 Views
Thanks, Les, for clearing that up. However I have one more query:

Suppose Subroutine A defines array X as allocatable and calls subroutine B where X is allocated and its size is returned in argument ISIZE.
If I now want to use the allocated array as an argument to subroutine C, called by subroutine A, is X now to be treated like an ordinary array X of size ISIZE? i.e. in subroutine C can it be dimensioned as
INTEGER*4 X(ISIZE)? Is the following correct

SUBROUTINE A(...)
INTEGER(DWORD), ALLOCATABLE :: X(:)
INTEGER(DWORD) ISIZE
INTERFACE
SUBROUTINE B(X,ISIZE)
INTEGER(DWORD), ALLOCATABLE :: X(:)
INTEGER(DWORD) ISIZE
END SUBROUTINE
END INTERFACE

INTERFACE
SUBROUTINE C(X,ISIZE)
INTEGER(DWORD) ISIZE, X(ISIZE)
END SUBROUTINE
END INTERFACE

CALL B(X,ISIZE)
CALL C(X,ISIZE)
...
END SUBROUTINE A

SUBROUTINE B(X,ISIZE)
INTEGER(DWORD), ALLOCATABLE :: X(:)
INTEGER(DWORD) ISIZE
....
ISIZE=10000
ALLOCATE(X(ISIZE))
...
END SUBROUTINE B

SUBROUTINE C(X,ISIZE)
INTEGER(DWORD) ISIZE, X(ISIZE)
...
END SUBROUTINE C

0 Kudos
Les_Neilson
Valued Contributor II
2,063 Views

Yes it can be passed to C as an "ordinary" array. I do this all the time with my allocated arrays.
Les

0 Kudos
Steven_L_Intel1
Employee
2,063 Views
Oh, CVF help. Fortran 95 did not allow allocatable dummy arguments. This was first added as a "TR" and then incorporated into F2003. CVF added it at the very end of development, and your manual probably predates that. Same thing with allocatable components of derived type.
0 Kudos
anthonyrichards
New Contributor III
2,063 Views
Thanks to you both.
0 Kudos
Reply