Passing arrays as smaller than they actually are

那年仲夏 提交于 2021-01-27 12:03:51

问题


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 if foo 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!