1

I was told a long time ago that in FORTRAN, everything is passed by value. Therefore I would need to do this (provided mySubroutine is suitably defined elsewhere):

double precision :: myArray(2)
myArray(1:2) = (/ 2.3d0,  1.5d0 /)
CALL mySubroutine(myArray)

However, I also found that the program compiles and runs as expected if I do this

CALL mySubroutine((/ 2.3d0,  1.5d0 /))

without needing to define an intermediary array myArray. I thought that I was passing myArray into mySubroutine by reference. What is going on under the hood in the second version? Is the compiler unpacking the subroutine call, declaring a temporary variable only to pass it by reference?

QuantumDot
  • 293
  • 1
  • 3
  • 10
  • 1
    In fortran by default everything is (or behaves as if) passed by reference. In the second case you are correct the compiler effectively makes a temporary array and passes the reference. note if `mysubroutine` modifies its arguments it will modify `myarray` in the first case and do something unpredictable in the second. – agentp Jul 18 '17 at 04:18

1 Answers1

3

To a large extent, trying to classify Fortran procedure calling with pass-by-reference and pass-by-value is not too helpful. You can find more detail on that in response to questions like this one and this one.

In short, generally procedure references are such that changes to a variable in a procedure are reflected in the variable where the procedure was referenced. In some cases a compiler may choose to do copy-in/copy-out, and in others it effectively must. Equally, the value attribute of a dummy argument specifies that an anonymous copy be made.

Where this question adds something a little different is in the use of an expression such as in

call mySubroutine([2.3d0, 1.5d0])  ! Using F2003 array constructor syntax

Is the compiler creating a temporary variable?

Admittedly, this is perhaps just a looseness in terminology but it's worth saying that there is certainly no variable involved. [2.3d0, 1.5d0] is an expression, not a variable. Crucially this means that it cannot be modified (appear in a variable definition context) in the procedure. Restrictions that apply in the case using an expression rather than a (temporary) variable include:

  • the dummy argument associated with an expression may not have the intent(inout) or the intent(out) attribute;
  • if the dummy argument hasn't an intent attribute then that argument may not be modified if the associated actual argument is an expression.

Now, if the dummy argument has the value attribute the effect of the procedure is the same whichever way it is referenced.

To conclude, the program may work just as well with an expression instead of an intermediate variable. If it doesn't that's because of violation of some aspect of Fortran. How it works is a problem for the compiler not the programmer.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • Thank you for your helpful answer! A motivation for my asking this question is that this code is part of a function that will be looped over many times, and I am wondering if I am shaving of some time by inserting the expression directly into `mySubroutine` (which has the `intent(in)`). That way, `myArray` isn't reinitialized over and over again. – QuantumDot Jul 18 '17 at 11:20