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

VALUE Attribute Vs INTENT(IN)

ScottBoyce
Novice
3,513 Views

This is just a general question for peoples opinions on the VALUE attribute used in subroutines. I know it The VALUE attributie is sometimes necessary for interoperability with C, but my interest is what would be the benefit beyond that compared to INTENT(IN). I am assuming  that it makes no sense to have both at the same time.

 

Below is a simple example of what I am talking about

[fortran]

SUBROUTINE DOUBLER(X,Y) 

  REAL,      VALUE::X

  REAL,INTENT(OUT)::Y

  Y=2.*X

END SUBROUTINE

[/fortran]

or

[fortran]

SUBROUTINE DOUBLER(X,Y) 

  REAL, INTENT(IN)::X

  REAL,INTENT(OUT)::Y

  Y=2.*X

END SUBROUTINE

[/fortran]

 

Or another example would be:

[fortran]

FUNCTION DOUBLER(X) RESULT(Y) 

  REAL, VALUE::X

  REAL::Y

  Y=2.*X

END FUNCTION

[/fortran]

or

[fortran]

FUNCTION DOUBLER(X)   RESULT(Y) 

  REAL::X                             !FUNCTION IMPLICITLY USES IN

  REAL::Y

  Y=2.*X

END FUNCTION

[/fortran]

0 Kudos
12 Replies
FortranFan
Honored Contributor III
3,513 Views

Use INTENT(IN) if your intent is that dummy argument should not be changed in the procedure e.g., not make it to the left-hand side of an assignment.

Use VALUE if your intent is to use the dummy argument the way "pass by value" arguments are used in languages such as C e.g., the dummy argument may change during the course of the procedure execution, but not referenced back to the caller.

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,513 Views

I haven't tried this, but you may also be able to use VALUE, INTENT(IN) for variables that you wish to be passed by value .AND. inhibit use on left hand side (or passed to routine that can modify it).

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
3,513 Views

VALUE has different meanings depending on whether you use BIND(C) or not. (And also /standard-semantics).

With BIND(C), it means pass by value. Without BIND(C), it means pass a writable copy by reference. You can write to either one, but the effect will be discarded on return.

The current ifort. though, misimplements the second case, causing VALUE to mean pass-by-value always. In 14.0 we added /assume:std-value to get the standard-specified behavior, and this is implied by /standard-semantics. In the future we might make this the default (probably not this year.)

0 Kudos
ScottBoyce
Novice
3,513 Views

I guess my main question is, outside of making the subroutine work better with C, is there any advantage over using just an internal temp variable. I often have subroutines using the following form.

[fortran]

SUBROUTINE DOUBLER(X,Y) 
  REAL, INTENT(IN)::X
  REAL,INTENT(OUT)::Y
  REAL::XX
  XX=X
  XX=2*X
  Y=XX
END SUBROUTINE

[/fortran]

This is a ridiculously simple example, but my main question is, other then shorter code, is there any benifit to changing the code too

[fortran]

SUBROUTINE DOUBLER(X,Y) 
  REAL, VALUE::X
  REAL,INTENT(OUT)::Y
  X=2*X
  Y=X
END SUBROUTINE

[/fortran]

 

0 Kudos
mecej4
Honored Contributor III
3,513 Views

You could make the subroutine even shorter, with the only executable statement being "Y = 2*X".

We need a better example in order to bring out the issues involved.

0 Kudos
ScottBoyce
Novice
3,513 Views

I know you could collapse that down. I just was using that to illustrate what I was trying to say. Typically I make copies for more complicated code or when a string is being passed in that is converted to upper case.

0 Kudos
Steven_L_Intel1
Employee
3,513 Views

It depends on what sort of argument you'd tend to pass in. I like using local variables when an argument is optional, so I can set a default. I'm not particularly in favor of the idea of assigning to a VALUE argument as I think that is less clear to the reader regarding what is going on.

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,513 Views

>> Without BIND(C), it means pass a writable copy by reference

Just how does this relate with fastcall (pass value in register)?
a) stack location reserved but not written, value in register, token for variable marked as modified (0 writes, 0 reads)
b) stack location obtained, value written, call made, value read, ... (1 write, 1 read)

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
3,513 Views

jimdempseyatthecove wrote:

>> Without BIND(C), it means pass a writable copy by reference

Just how does this relate with fastcall (pass value in register)?

It doesn't. Such a routine is not interoperable.

0 Kudos
ScottBoyce
Novice
3,513 Views

 

Thanks Steve and Jim for your help as always was confused Jim by "pass a writable copy by reference". does that mean that it makes a copy of the referenced location or still operates on the actual original variables location.

For Steve, how would you initialize an optional variable with VALUE? Below is an example function that I was interested in applying this too. This function takes in a string (Ln) and processes it to a certain output (RES). One of the things I do in the subroutine is make a copy of LN, convert that copy to upper case, and use the copy for processing. The optional logicals (CHECKCASE,CHECKKEY) are also used for additional checks by the function for sections of the code where speed is not as important as debug information. Since the logicals are optional variables would they benefit from VALUE and how would I initialize them if they are not present. Right now I just have a local copy of a variable that set to a default value and when the optional are present overwritten with their values.

 

[fortran]

     FUNCTION LINEINTERPRETER(Ln,NAMES,NAMEVALUES,CHECKCASE,CHECKKEY) RESULT(RES)

      CHARACTER(*),                 INTENT(IN)::Ln

      CHARACTER(*),    DIMENSION(:),INTENT(IN)::NAMES

      DOUBLE PRECISION,DIMENSION(:),INTENT(IN)::NAMEVALUES

      LOGICAL,         OPTIONAL,    INTENT(IN)::CHECKCASE

      LOGICAL,         OPTIONAL,    INTENT(IN)::CHECKKEY

      DOUBLE PRECISION                        ::RES

[/fortran]

 

Thanks again for all your help.

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,513 Views

RE: Steve's: Without BIND(C), it means pass a writable copy by reference

Meaning when an optional argument with VALUE and without BIND(C)

is present, a copy is made and the reference to the copy is passed
is not present, a NULL reference is passed, thus permitting testing for presence

I think this was the principal reason for doing it this way.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
3,513 Views

I would not use VALUE for this purpose. Here's how I handled such things in the WinPrint sample:

logical(4), intent(in), optional :: Default_Printer
...
logical(4), parameter :: DDefault_Printer = .TRUE.  ! Use default printer?
logical(4) :: WDefault_Printer
...
! Establish defaults for optional arguments
!
WDefault_Printer = DDefault_Printer
...
if (present(Default_Printer)) then
  WDefault_Printer = Default_Printer
  end if

I then used WDefaultPrinter in the rest of the code.

While the standard allows VALUE for non-BIND(C) routines, I don't find that of much "value" since, as I mentioned above, it obscures behavior.

0 Kudos
Reply