Объявление фиктивного аргумента массива явных форм в Фортране - PullRequest
2 голосов
/ 24 мая 2019

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

Пример выглядит следующим образом:

module mp
implicit none
contains
  subroutine p(b)
    integer :: m=4, n=4 !not integer,parameter :: m=4, n=4
    integer :: b(m,n)
  end subroutine p
end module mp

Гфортран повысит Error: Variable 'm' cannot appear in the expression at (1)

В этом примере я могу использовать integer,parameter :: m=4, n=4, чтобы избежать этого, но я не понимаю, почему исходный случай не работает, учитывая тот факт, что границы / экстенты массивов явных форм не нужно знать при компиляции время. Работает модифицированная версия приведенного выше примера:

module mp
implicit none
integer :: m=4, n=4
contains
  subroutine p(b)
    integer :: b(m,n)
  end subroutine p
end module mp

Учитывая небольшую разницу между двумя примерами, я ожидаю, что оба они сработают, но на самом деле первый не сработает. Может ли кто-нибудь объяснить причину?

Обновление: я обнаружил, что это очень тонкая проблема, потому что она зависит от того, содержится ли подпрограмма в модуле или является автономной, она также зависит от версии gfortran. Я разместил примеры в области ответов.

Ответы [ 3 ]

3 голосов
/ 24 мая 2019

Формально существуют требования к границам такого массива явная форма . Они не просто отображаются на «не должны быть известны во время компиляции».

Для явной формы массива границы массива должны быть выражениями спецификации . Часто такие границы должны быть константными выражениями , но это не относится к фиктивным аргументам. Отчасти это порождает (ошибочную) мысль, что их не нужно знать во время компиляции.

Однако ограничения для выражения спецификации все же должны быть соблюдены. Их можно найти в Fortran 2018 10.1.11. В частности, локальная переменная (даже сохраненная) может не отображаться в выражении спецификации.

Для примеров вопроса используйте именованные константы, например, с

integer, parameter :: m=4, n=4

допускается в выражении спецификации. Действительно, выражения спецификации m и n являются даже константными выражениями в этом случае.

Если бы у нас было

function p(b,m,n)
  integer m, n, b(m,n)
end function

тогда у нас есть допустимые выражения спецификации для границ массива, хотя m и n не являются константами.

1 голос
/ 25 мая 2019

Правильный обходной путь - поместить тело процедуры в конструкцию BLOCK:

module mp3
contains
  subroutine p(b)
    implicit none
    integer :: m=4, n=4 
BLOCK
    integer :: b(m,n)
END BLOCK
 end subroutine p
end module mp3

О том, что он работает в gfortran-8 в качестве отдельной подпрограммы, следует сообщать об bugzilla.У вас есть хороший минимальный пример там.

РЕДАКТИРОВАТЬ : я не заметил, что b был фиктивным аргументом.Я больше думал о чем-то вроде

module mp3
contains
  subroutine p(x)
    implicit none
    real x
    integer :: m=4, n=4 
BLOCK
    integer :: b(m,n)
END BLOCK
 end subroutine p
end module mp3

Но, как показывает пример, подход BLOCK просто не может работать.Также gfortran 8.1.0 отклоняет форму с помощью отдельной подпрограммы:

  subroutine p(x)
    implicit none
    real x
    integer :: m=4, n=4 
    integer :: b(m,n)
 end subroutine p

Error: Variable 'm' cannot appear in the expression at (1)

(как и должно быть)

1 голос
/ 24 мая 2019

Наконец, я обнаружил, что это очень тонкая проблема, поскольку она зависит от версии gfortran, а также от того, содержится ли подпрограмма в модуле или является автономной.Ни gfortran-4.8, ни gfortran-8 не могут успешно скомпилировать следующий код:

module mp3
contains
  subroutine p(b)
    implicit none
    integer :: m=4, n=4 
    integer :: b(m,n)
 end subroutine p
end module mp3

Но если мы рассмотрим отдельную подпрограмму следующим образом:

 subroutine p(b)
    implicit none
    integer :: m=4, n=4 
    integer :: b(m,n)
 end subroutine p

Тогда gfortran-4.8 все равно отклонит этоформа, но gfortran-8 принимает это, что может быть просто ошибкой в ​​gfortran-8, потому что дальнейшее тестирование (пользователем5713492) показывает, что gfortran-8.1.0 также отклоняет эту форму.

В итоге, локальные переменные подпрограммыне допускаются в выражении спецификации массивов фиктивных аргументов.

Использование локальных непостоянных переменных в выражениях спецификации не очень часто необходимо.Так что запрещать такое использование не страшно.

...