问题
In the following code, I declare an array mass
with 20 elements. When passed to the subroutine foo
, foo
is told that mass
has only 10 elements. However, I can still access the 20th element. My questions are:
Why can I pass an array to a subroutine and tell the subroutine the wrong size for the array?
Why can I still access the 20th element even though the subroutine thinks it only has 10 elements?
Would any changes I make to the 20th element in the array while in
foo
remain with the array just the same as iffoo
knew the proper size of the array?
Here is the code:
program test
implicit none
integer num2,i
real*8 mass(20)
num2=10
do i = 1,num
mass(i) = 1.d0
end do
call foo(num2,mass)
end
subroutine foo(num2,mass)
integer num2
real*8 mass(num2)
write(*,"(A20,E15.9)") "first one:",mass(1)
write(*,"(A20,E15.9)") "tenth one:",mass(10)
write(*,"(A20,E15.9)") "twentieth one:",mass(20)
continue
end
Note: This situation of a subroutine being told the wrong size for an array is one I am encountering in someone else's code I am trying to modify for my own usage.
回答1:
There are a couple of misconceptions underlying your question which I'll address in this answer. Some practical implications are given in the answer by M. S. B..
You say that you declare an array mass
with twenty elements, but that foo
is told that it has only ten. This is not correct.
What you have are actually two distinct entities: an array mass
in the main program, with twenty elements, and an array (also called mass
) of size ten in the subroutine foo
.
The "passing" is establishing an association (so-called argument association) between those two entities. The array called mass
in the main program is the actual argument in the subroutine and the array called mass
in the subroutine is the dummy argument.
The dummy argument is an array of explicit shape, extent num2
(which is also argument associated with the num2
of the main program). The first num2
elements of the dummy argument are associated with the first num2
elements of the actual argument. [This leads to the requirement that there are at least num2
elements in the array in the main program.]
So, the answer to your first question
Why can I pass an array to a subroutine and tell the subroutine the wrong size for the array?
is just this: you aren't telling it the wrong size, you are merely saying that the array in the subroutine corresponds to the first num2
elements of the argument.
Coming to
Why can I still access the 20th element even though the subroutine thinks it only has 10 elements?
This is a programming error. You are not allowed to use a subscript value larger than the extent of the array. What happens when you try this is up to the compiler. As the other answer says, it's quite possible that this is just accessing (because of the way the association is implemented) that location in memory corresponding to the large element of the actual argument. But equally the compiler could complain (especially with those checking compilation options chosen), or if the passing is done with temporary copying the thing could crash. [This latter is unlikely.]
Finally
Would any changes I make to the 20th element in the array while in foo remain with the array just the same as if foo knew the proper size of the array?
This is again implementation specific. There is no correct Fortran answer, as your program isn't conforming. As with the previous point, if that's an area of memory corresponding to the appropriate element of the actual argument and there's no bounds checking going on the changes could persist. If the compiler chose to do a copy there could either be a crash or the changes outside the bounds could be ignored on return. [Again, these last two are unlikely as it would require the compiler to be "clever".]
回答2:
Why can I pass an array to a subroutine and tell the subroutine the wrong size for the array? Because Fortran allows you to use a portion of an array.
Why can I still access the 20th element even though the subroutine thinks it only has 10 elements?
Because 1) the array elements are consecutive in memory so the indexing reaches the 20th element, and 2) Fortran-produced programs normally doesn't check whether or not the programming is making performing invalid array subscripting. Most compilers have options to insert such checks, e.g., -fcheck=bounds
or -fcheck=all
for gfortran.
Would any changes I make to the 20th element in the array while in foo remain with the array just the same as if foo knew the proper size of the array? Yes. If you did this and the original array didn't have 20 elements, you would alter an unrelated memory location, with bad results.
来源:https://stackoverflow.com/questions/34520550/passing-arrays-as-smaller-than-they-actually-are