问题
Suppose I have something like:
real, dimension(:), allocatable :: S
integer, dimension(:) :: idx
...
S = S(idx)
where S
and idx
are properly allocated/initialized before the assignment.
What does the Fortran standard(s) say, if anything, about the memory location (address) of S
? Should it stay in the same place after the assigment? Is it unspecified (up to the compiler to decide)? Does it make a difference if S
is not allocatable
?
Full example:
$ cat test.f90
program test
implicit none
real, dimension(:), allocatable :: S
integer :: i, idx(7) = [1,3,5,7,2,4,6]
allocate(S(size(idx)))
do i=1,size(S)
S(i) = i*i
end do
write(6,*) S
write(6,*) loc(S)
S = S(idx)
write(6,*) S
write(6,*) loc(S)
S(:) = S(idx)
write(6,*) S
write(6,*) loc(S)
deallocate(S)
end program
$ sunf90 -V
f90: Studio 12.6 Fortran 95 8.8 Linux_i386 2017/05/30
$ sunf90 test.f90 ; ./a.out
1.0 4.0 9.0 16.0 25.0 36.0 49.0
37518752
1.0 9.0 25.0 49.0 4.0 16.0 36.0
37519840
1.0 25.0 4.0 36.0 9.0 49.0 16.0
37519840
(assuming loc
gives something related to the address of the array)
回答1:
In your example, it matters whether idx
has the same extent (number of elements) as S
. If it does, then the shape of S(idx)
is the same as that of S
and the standard says that no reallocation of S
occurs. But if they are different, then the standard says S
is deallocated, then reallocated to the shape of S(idx)
. If this deallocation/reallocation occurs, it is unpredictable (and probably unlikely) if the base address remains the same.
You then asked what if S
was not allocatable - in this case, the shapes must match and it's just a copy of data, though possibly via a temporary array since there is overlap.
-- Edit August 24, 2019 --
I polled the J3 (US Fortran standards committee) email list on this. The consensus was that, in the absence of TARGET
, the "changing address" was standard-conforming, though more than one member questioned whether it was a good idea. The compiler developers evidently feel that allocating new storage and doing a single copy is faster than keeping the same storage and doing two copies (one to a temp and then one back to S
.) I might see this as beneficial if a lot of data was being copied - maybe - but not in smaller cases.
In any event you can, as you discovered, disable this behavior by giving S
the TARGET
attribute.
回答2:
The Fortran standard says little about "memory locations". It does, however, have (Fortran 2018, Note 16.24):
It is expected that the implementation of allocatable objects will typically involve descriptors to locate the allocated storage
In the case of the question, though, it can be reasonably expected that no implementation will always keep S
having the same address for the first element after assignment: S
after the assignment may be arbitrarily larger than S
before the assignment. In such cases a new allocation of memory may be required.
If S
is not allocatable (strictly, of deferred length) its size won't change as a result of the assignment: however, it would be compatible (in many but not all cases) with the standard for the base address of S
to move to a new location comparable to an array-temporary.
In cases where storage association is required (which does restrict the moving of variables in memory), the use of allocatable variables is heavily restricted.
来源:https://stackoverflow.com/questions/57606191/memory-location-of-fortran-allocatable-arrays-on-assigment