Почему мы не можем определить размер массива по переменной? - PullRequest
0 голосов
/ 09 января 2019

Я обнаружил, что размер массива может определяться параметрами, но не переменными. Ниже приведен пример, объясняющий, что я говорю.

1-й пример - не работает:

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

2-й пример - рабочий:

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

В 1-м примере я ожидаю, что dimension может использовать переменную narr, так как narr определяется ПЕРВЫМ. Но я понял, что это может быть не так, поскольку создание переменной может не соответствовать порядку строк кода. Может быть, это только то, что человек с опытом работы с Python только так и подумает.

Во втором примере все работает отлично.

Я предполагаю, что разница связана с тем, КОГДА переменная и константа созданы. Может кто-нибудь объяснить тайну внутри него?

1 Ответ

0 голосов
/ 09 января 2019

В ваших примерах, поскольку integer, dimension(narr) :: Total не имеет атрибута allocatable или pointer, это либо статический массив, либо автоматический массив, в зависимости от контекста (я опускаю предполагаемый массив формы, потому что вопрос конкретно о определяющих массивах). В любом случае его размер должен быть постоянной времени компиляции или фиктивным аргументом. В первом примере narr не является ни тем, что делает его недействительным Fortran. Чтобы использовать narr в качестве неконстантной переменной для указания размера, вам необходимо объявить Total как динамический массив, включив атрибут allocatable или pointer. Это может привести к снижению производительности в зависимости от ситуации, но это обеспечивает большую гибкость в отношении того, как и где определяется граница массива.

Вот некоторые из распространенных способов определения статических и динамических массивов в 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

(здесь я опускаю более современные функции, такие как автоматическое распределение при назначении.)

...