When I define a variable (local in a subroutine, module/program variable, dummy argument) then my understanding is that I choose exactly one of the following cases:
integer :: x
integer, pointer :: x
integer, value :: x
Is that correct?
The value
attribute can only be used for dummy arguments. The pointer
and “unspecified” can be used for any variable.
Furthermore, when I have a pointer
variable, and I use it in an expression, then the result is not a pointer, correct? For example, if I have a subroutine like this:
subroutine f2(x)
integer, pointer, intent(in) :: x
print *, x
end subroutine
Then I am required to call it with a pointer variable, such as:
integer, pointer :: y
allocate(y)
y = 5
call f2(y)
And that works, but the following does not work:
call f2(y+y)
Nor:
call f2((y))
From this I concluded that when a variable becomes an expression, it is effectively a “value”, even though you can’t actually declare a variable to have a value
attribute outside a dummy argument. Is that correct?
So the rules of pointers are roughly:
- If a pointer variable is used in an expression, it is automatically “dereferenced” and it becomes a value
- The result of an expression is a value
- When a value is assigned (using
=
) to a pointer variable, the pointer variable first gets “dereferenced” before assigning the value to it - When a dummy argument is:
- a pointer: then the actual argument must also be a pointer — so you cannot pass in an expression
- a value: then the actual argument gets “dereferenced” first, and in
bind(c)
procedures the argument is passed by value - unspecified: then the compiler is free to pass either by value or by reference internally (i.e., the user does not see that, you can pass in an expression), but in
bind(c)
procedures, it is passed by reference
Is there any other catch, or is that it?
Last question: Besides bind(c)
, is there any difference between the following two procedures from a user perspective:
subroutine g1(x)
integer, value, intent(in) :: x
print *, x
end subroutine
subroutine g2(x)
integer, intent(in) :: x
print *, x
end subroutine
In other words, is the value
attribute only useful for the bind(c)
subroutines? The value
attribute is described in the section “8.5.18 VALUE attribute” of the Fortran 2018 standard. It says that “An entity with the VALUE attribute shall be a dummy data object.”. It says “dummy data object is a dummy argument that is a data object”. Finally, a “data object is a constant (7.1.4), variable (9), or subobject of a constant (5.4.3.2.4)”.