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

Passing user-defined type variables via the argument list

John6
Novice
727 Views

I know that Fortran variables (by default), when passed from one subroutine to another via the argument list, are passed by reference.

Is there any difference if a Fortran user-defined type (ie, structure) variable is passed from one subroutine to another subroutine via the argument list?

In other words, is the structure still passed by reference or is a copy made? (I have always assumed it was passed by reference like any other variable).

Also, is there a difference in the declaration of arrays passed via the argument list as (*) vs. (some known value)?

For example, in the following subroutine, assume a is a structure (user-defined type) of MyType and b is an array of type real.

Subroutine foo(a, b)

Implicit None

Type(MyType) :: a <==== Is a copy made of the structure passed via the arg list or is this passed by reference?

Real :: b(*) <==== Assuming you know the dimension of b in this subroutine (say it's a global constant), what is the difference between declaring it as b(*) or b(TheKnownDimension)? Which is better?

End Subroutine foo

0 Kudos
9 Replies
Steven_L_Intel1
Employee
727 Views
The only time a copy is made is if the actual argument is a non-contiguous array slice and there is no explicit interface visible indicating that the corresponding dummy argument is a deferred-shape array.

As for b(*) vs, b(known-dimension), the latter is always preferable if you know it. You could also have b(:) where the bounds would get passed in automatically, but this requires an explicit interface to be visible.
0 Kudos
John6
Novice
727 Views
So if the structure variable which was passed in is not an array, there would be no question: no copy would be made (ever).
0 Kudos
Steven_L_Intel1
Employee
727 Views
Onemore exceptions - if an explicit interface was visible where the dummy argument had the VALUE attribute. Otherwise, no copy.
0 Kudos
John6
Novice
727 Views
Thanks. I have heard it from some who are more familiar with C programming that if a Fortran array argument list variable wasdeclared inside the subroutine as (*), it would be passed in by reference, wheras if it wasdeclared as (SomeKnownValue), a copy of the variable was made upon entering the subroutine and (somehow) copied back upon exiting the subroutine. I had my doubts but wanted to verify. I had also wanted to double-check that the user-defined type (which can be quite big, but not arrayed) which I pass from sub-to-sub is not resulting in multiple (hidden) copies being made which would slow the overall program execution.
0 Kudos
TimP
Honored Contributor III
727 Views
Intel compilers pass variables by "reference," including as default in iso_c_binding (when value is not specified). Any context where you specify an array section to pass to C (or Fortran, in the absence of in-lining) may result in a copy made on the Fortran side. It's probably worth while to check in the actual case you have in mind.
0 Kudos
John6
Novice
727 Views

Thanks, I'm still trying to wrap my mind around this topic...
So, say I have a user-defined type name "a" whichcontains a double dimensioned variable real member b(10,2).
I pass b in from one subroutine to another via the argument list like: Call foo (a%b(:,m)) where m is say, 2.
Inside sub foo, b is declared as Real :: b(10)
Am I passing an "array slice" of b into sub foo? (I'm assuming yes, but I would like to be sure).
This then would result in a copy of b being made? Is a copy of "a" (the containing structure)made (in my case undesirable since a is quite big and contains a lot more elements)?

0 Kudos
Steven_L_Intel1
Employee
727 Views
In the specific case you mention, no copy would be made. That's becsause all of the elements of a%b(:,m) are contiguous in memory. If the compiler can tell that the argument is contiguous, it just passes the address of the first element. Sometimes it uses run-time code to figure this out, especially if you are using pointers.

If you had instead written a%b(m,:), then a copy would be made because the elements are not contiguous.
0 Kudos
John6
Novice
727 Views
OK,that makes sense to me (in general, Itry not topass non-contiguous array items from sub-to-sub, because it gets complicated to debug if a problem arises).

Just to be clear, if I had written a%b(m,:) as you say, a copy of "a" would not have been made, correct? Only a copy of "b" would be made?
0 Kudos
Steven_L_Intel1
Employee
727 Views
Only the array slice being passed would be copied to make it contiguous. It would also be copied back into the original array after the call returns, unless INTENT(IN) was specified in an explicit interface.
0 Kudos
Reply