Ken T
Ken T

Reputation: 2553

Why can't we define the array size by a variable?

I found that the array size can be defined by parameters but not variables. An example is given below to explain what I am saying.

1st Example - Not working:

integer :: narr=100
integer, dimension(narr) :: Total

2nd Example - Working:

integer, parameter :: narr=100
integer, dimension(narr) :: Total

In the 1st example, I expect the dimension can use the variable narr as narr is defined FIRST. But I realized that this may not be true as the creation of variable may not follow the order of my code lines. Maybe this is only what a person with Python background only would think so.

In the 2nd example, things work perfectly.

I speculate that the difference is related to WHEN the variable and constant are created. Can someone explain the mystery inside it?

Upvotes: 2

Views: 1402

Answers (1)

Raul Laasner
Raul Laasner

Reputation: 1585

In your examples, since integer, dimension(narr) :: Total does not have an allocatable or pointer attribute, it is either a static array or an automatic array, depending on the context (I'm leaving out assumed shape array because the question is specifically about defining arrays). In either case, its size must be a compile time constant or a dummy argument. In the first example, narr is neither which makes it invalid Fortran. In order to use narr as a non-constant variable to specify the size, you would need to declare Total as a dynamic array by including the allocatable or pointer attribute. This might have a performance penalty depending on the situation, but it allows more flexibility in how and where the array bound is defined.

Here are some of the common ways to define static and dynamic arrays in Fortran:

  ! Static
  call test_fixed_size()
  call test_size_parameter()

  ! Dynamic
  call test_allocatable()
  call test_pointer()
  call test_automatic(10)

contains
  subroutine test_fixed_size()
    integer :: array(10)
    array = 1
  end subroutine test_fixed_size

  subroutine test_size_parameter()
    integer, parameter :: size = 10
    integer :: array(size)
    array = 1
  end subroutine test_size_parameter

  subroutine test_allocatable()
    integer, allocatable :: array(:)
    integer :: narr = 100
    allocate(array(narr))
    array = 1
  end subroutine test_allocatable

  subroutine test_pointer()
    integer, pointer :: array(:) => null()
    integer :: narr = 100
    allocate(array(narr))
    array = 1
    deallocate(array)
  end subroutine test_pointer

  subroutine test_automatic(size)
    integer, intent(in) :: size
    integer :: array(size)
    array = 1
  end subroutine test_automatic
end program

(I'm leaving out more modern features here such as automatic allocation on assignment.)

Upvotes: 4

Related Questions