Matrix index-pointer confusion

Opinions differ on this matter. I suppose that one problem is this mode of argument passing is intrinsically unsafe and a one-off mistake will easily cause an out-of-bounds violation. It also isn’t “rank-safe”.

The “modern” approach of using assumed-shape arrays is safer in that sense, but it can introduce some performance penalties (contiguous vs non-contiguous code paths).

In performance-oriented codes, explicit-shape array arguments (which allow sequence association) are still common. Here’s a related discussion: What's the purpose of array size inside subroutine arguments? - #8 by ivanpribec

In your second example I think it makes more sense to compare versus assumed-shape arguments:

Subroutine print_matrix(A)
   Real(dp) :: A(:,:)

This allows you to pass a non-contiguous array section (a so-called slice), without making an extra copy. In practice compilers will pass a “dope array” that includes the array rank, shape, and strides.

Edit: here’s a small program to demonstrate the concept.

program demo
implicit none
integer, parameter :: dp = kind(1.0d0)
real(dp) :: A(8,8)
call print_contig(A(:,:3))
call print_contig(A(3:5, 4:5))
contains
    subroutine print_contig(A)
        real(dp), intent(in) :: A(:,:)
        print *, is_contiguous(A)
    end subroutine
end program

Edit 2: I’ve always thought Fortran is easier than C++ with its complicated argument passing semantics, with pass by value (which includes pointers) and pass by reference, not to mention the whole story with lvalues and rvalues. In Fortran it’s the array dummy argument semantics which are confusing (but powerful).

1 Like