Multidimensional Arrays as Arguments

When passing a multidimensional array as an argument to a subprogram, is is even more critical that the dimensions are known.

With a one-dimensional array, the subprogram must know the size of the array in order to avoid out-of-bounds errors.

With a multidimensional array, we still have the possibility of out-of-bounds errors. In addition, if the correct dimensions are not known to the subprogram, it will not be able to compute the correct location of an element from the subscripts! Look again at the memory map of a small 2D array:

        double precision :: matrix(2, 3)
        
        Memory map:
        
        2000    matrix(1,1)
        2008    matrix(2,1)
        2016    matrix(1,2)
        2024    matrix(2,2)
        2032    matrix(1,3)
        2040    matrix(2,3)
        

The memory address of an element is computed as:

address(r, c) = base + (total-rows * (c-1) + (r-1)) * sizeof(type)

For an array of double precision values based at address 2000:

address(r,c) = 2000 + (2 * (c-1) + (r-1)) * 8

address(2,3) = 2000 + (2 * 2 + 1) * 8 = 2040

Since the calculation of an address involves the total number of rows in the matrix, we must at least get this right just to be able access the array elements correctly. Getting the number of columns right is also essential to prevent out-of-bounds problems.

        subroutine print_matrix(matrix, rows, cols)
            ! Disable implicit declarations (i-n rule)
            implicit none
            
            ! Dummy variables
            integer, intent(in) :: rows, cols
            double precision, intent(in) :: matrix(rows, cols)
        
            ! Local variables
            integer :: r
        
            do r = 1, rows
                print *, matrix(r, 1:cols)
            enddo
        end subroutine