4

Okay, so yesterday I had a co-worker coming into my office and asking me a question about Fortran code that he had to work with.

Basically, the code that he works with has a long, multidimensional array, and a subroutine that expects just this long, multidimensional array as a parameter.

However, the code calling that subroutine only passes the first element of the array. Yet the code works. So he asked me how that could be.

I haven't seen his particular code, but here's an example how I understand the issue (and it works!):

subroutine print_array(a)
    implicit none
    integer :: a(10)
    write(*, *) a
end subroutine print_array

program passing
    implicit none
    integer :: i(10)
    i = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
    call print_array(i(1))
end program passing

So I told him that Fortran stores arrays sequentially, and the location of the array is the same as to the first element, and since the subroutine expects a certain shape, it knows how far to read along this sequence, and so on.

I also told him that this was bad programming practice and that he shouldn't write this kind of code himself.

But since then I have been wondering: Why did whoever wrote this do it this way in the first place? Is there any reason to do that? (It doesn't even have to be a good reason.)

Or am I right and this is just silly and far too error-prone?

chw21
  • 7,970
  • 1
  • 16
  • 31

1 Answers1

5

Your explanation of how this works is correct. Your aversion to following this outdated practice is widely supported.

As for the reason, I've forgotten (though long ago I used to do it to -- like driving home from the pub and smoking, everyone did and thought nothing of it) but perhaps the earliest versions of the language didn't support passing the whole array as a parameter. Perhaps someone else, whose brain is not addled by the potent mix of booze, tobacco and FORTRAN (that's right, shout it out) remembers more clearly.

High Performance Mark
  • 77,191
  • 7
  • 105
  • 161
  • This oudated practice makes sense if you consider Fortran as a low level language (or high-level assembly). When you pass the address of the 1st element, if you change the declaration of the array from `i(10)` to `i(0:10)`, passing `i(1)` will not break your code but passing `i` will as the array will be shifted by 1 element. And if you pass `i(1:10)`, the compiler may create a temporary copy of the array (although I am not sure it is still true today) which will slow down the execution. – Anthony Scemama Feb 26 '16 at 10:10
  • I don't buy this explanation. But the good thing is that a temporary array is impossible which is good for non-blocking MPI. But I still pass the whole array instead and use MPI subarray datatypes, not vectors. – Vladimir F Героям слава Feb 26 '16 at 21:40
  • I have also seen this in old code for the reason High Perforamance Mark states. The compilers at the time would throw an error if you did "call print_array( i )", because it knew "i" should be an arrary reference, so use "i(1)" to pass the address of the first array element and let the subroutine use that as a reference to the entire contiguous array. – Mark Diaz Oct 30 '19 at 21:35