- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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]
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>> 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page