fortranfortran2003

Non-one indexed array from associate


I would like to have an associate that points to an array (or parts thereof) and is not one indexed. The following program illustrates the problem:

program test_associate
    implicit none(type, external)
    integer, parameter :: N = 10
    integer :: i, A(0 : N - 1)

    A = [(i, i = lbound(A, 1), ubound(A, 1))]
    write(*, *) A(0), A(9)

    associate(B => A(0 : N - 1))
        write(*, *) B(9)    ! This writes 8 but should write 9
    end associate
end program

I tried

    associate(B(0 : N - 1) => A(0 : N - 1))
        write(*, *) B(9)
    end associate

but this is invalid syntax. (at least in my compiler which is gfortran 9.3)


Solution

  • The syntax

    associate (B(0:N-1) => ...)
    end associate
    

    is not valid in Fortran: the left-hand side of the association item must be a name. With just a name (which here would be B) it isn't possible to specify properties such as bounds.

    The bounds of the associating entity array (again, here B), are given by the results of using LBOUND on the right-hand side (the selector) (Fortran 2018, 11.1.3.3 p.1):

    The lower bound of each dimension is the result of the intrinsic function LBOUND (16.9.109) applied to the corresponding dimension of selector

    The referenced description of LBOUND explains how the bound is calculated in this case.

    Because A(0:N-1) is not a whole array, LBOUND returns 1, and so the lower bound of B in this case is itself 1.

    It is possible to have the lower bound of B be something other than 1: have the selector being a whole array. In

    associate(B => A)
    end associate
    

    B will have lower bound that of A.

    In conclusion: it's possible for an associate entity to have lower bound other than 1, but only when the thing it's associated with is a whole array. In particular, in associating with part of an array (and that can include all of the array, such as B => A(:), A(:) not being a whole array) the associating entity always has lower bounds 1.

    As Vladimir F says in another answer, a pointer can have bounds controlled as part of pointer assignment.