Passing arguments by reference or by value

To call subprograms written in languages other than Fortran (for example, user-written C programs, or operating system routines), the actual arguments may need to be passed by a method different from the default method used by Fortran. C routines, including those in system libraries, such as libc.a, require you to pass arguments by value instead of by reference. (Although C passes individual scalar array elements by value, it passes arrays by reference.)

You can change the default passing method by using the %VAL built-in function or VALUE attribute and the %REF built-in function in the argument list of a CALL statement or function reference. You cannot use them in the argument lists of Fortran procedure references or with alternate return specifiers.
%REF
Passes an argument by reference (that is, the called subprogram receives the address of the argument). It is the same as the default calling method for Fortran except that it also suppresses the extra length argument for character strings.
%VAL
Passes an argument by value (that is, the called subprogram receives an argument that has the same value as the actual argument, but any change to this argument does not affect the actual argument).

You can use this built-in function with actual arguments that are CHARACTER(1), BYTE, logical, integer, real, or complex expressions or that are sequence-derived type. Objects of derived type cannot contain pointers, arrays, or character structure components whose lengths are greater than one byte.

You cannot use %VAL with actual arguments that are array entities, procedure names, or character expressions of length greater than one byte.

%VAL causes XL Fortran to pass the actual argument as 32-bit or 64-bit intermediate values.

32-bit intermediate values
If the actual argument is one of the following:
  • An integer or a logical that is shorter than 32 bits, it is sign-extended to a 32-bit value.
  • An integer or a logical that is longer than 32 bits, it is passed as two 32-bit intermediate values.
  • Of type real or complex, it is passed as multiple 32-bit intermediate values.
  • Of sequence-derived type, it is passed as multiple 32-bit intermediate values.

Byte-named constants and variables are passed as if they were INTEGER(1). If the actual argument is a CHARACTER(1), the compiler pads it on the left with zeros to a 32-bit value, regardless of whether you specified the -qctyplss compiler option.

64-bit intermediate values
If the actual argument is one of the following:
  • An integer or a logical that is shorter than 64 bits, it is sign-extended to a 64-bit value.
  • Of type real or complex, it is passed as multiple 64-bit intermediate values.
  • Of sequence-derived type, it is passed as multiple 64-bit intermediate values.
Byte-named constants and variables are passed as if they were INTEGER(1). If the actual argument is a CHARACTER(1), the compiler pads it on the left with zeros to a 64-bit value, regardless of whether you specified the -qctyplss compiler option.

If you specified the -qautodbl compiler option, any padded storage space is not passed except for objects of derived type.

VALUE attribute
Specifies an argument association between a dummy and an actual argument that allows you to pass the dummy argument with the value of the actual argument. Changes to the value or definition status of the dummy argument do not affect the actual argument.

You must specify the VALUE attribute for dummy arguments only.

You must not use the %VAL or %REF built-in functions to reference a dummy argument with the VALUE attribute, or the associated actual argument.

A referenced procedure that has a dummy argument with the VALUE attribute must have an explicit interface.

You must not specify the VALUE attribute with the following:
  • Arrays
  • Derived types with ALLOCATABLE components
  • Dummy procedures
  EXTERNAL FUNC
  COMPLEX XVAR
  IVARB=6

  CALL RIGHT2(%REF(FUNC))       ! procedure name passed by reference
  CALL RIGHT3(%VAL(XVAR))       ! complex argument passed by value
  CALL TPROG(%VAL(IVARB))       ! integer argument passed by value
  END