Инициализация общего блока Fortran

Новичок в Fortran, меня попросили поработать над старой кодовой базой Fortran, написанной на Fortran 77 с компилятором Salford/Silverfrost (первоначальный разработчик скончался).

Оригинальный разработчик широко использует именованные блоки COMMON (для эмуляции глобальных переменных, AFAIU), и он использует EQUIVALENCE для (повторной) инициализации блоков, когда это необходимо, как в этом фрагменте кода:

      IMPLICIT REAL*8 (A-H,O-Z)

      COMMON/COMMF2D/
     * ASCN(0:99,0:20,0:4)   
     *,FEMPTY2(8700)

      DIMENSION KLCKF2D(38400)
      EQUIVALENCE (KLCKF2D,ASCN)

      DO I= 1,38400                                              
      KLCKF2D(I)= 0
      END DO

Это приемлемая практика программирования или просто хак? Кроме того, поскольку я пытаюсь перенести код на GFortran, можно ли его перенести? (Я понимаю, что такие объявления, как REAL*8, являются просто намеками для компилятора и не гарантируются)


person Wolfy    schedule 08.08.2012    source источник
comment
Говоря о переносимости, ни один код, который использует жестко заданные постоянные значения для размеров типов (например, REAL*8) или для типов типов (например, REAL(KIND=8)), не является переносимым. В переносимом коде Fortran 90+ вы должны вызвать SELECTED_REAL_KIND(), чтобы получить параметр вида, который гарантирует определенную точность и экспоненциальный диапазон.   -  person Hristo Iliev    schedule 08.08.2012


Ответы (1)


EQUIVALENCE ничего не делает, уж точно ничего не инициализирует, EQUIVALENCE — это определение или объявление. В наши дни (и с момента публикации стандарта Fortran 90 с постоянно растущей силой) EQUIVALENCE является хаком, и его следует избегать везде, где это возможно.

Оператор объявляет, что 2 переменные совместно используют хранилище (то, что в стандартах Fortran называется storage-association). Одна интерпретация этого состоит в том, что имена, которые эквивалентны, являются просто псевдонимами, но (неправильное) использование оператора позволяет программисту делать некоторые другие вещи, которые профессиональные инженеры-программисты 21-го века считают изворотливыми.

Например, и это относится к опубликованному вами фрагменту, EQUIVALENCE можно использовать для того, чтобы переменные разных типов совместно использовали одно и то же хранилище. У вас есть массив с именем ASCN, который (неявно) имеет тип REAL*8 и эквивалентен массиву с именем KLCKF2D, который (опять же неявно) имеет тип INTEGER. Это означает, что если вы обращаетесь к хранилищу под одним именем, битовые шаблоны интерпретируются как REALs, при использовании другого имени они интерпретируются как INTEGERs -- и обратите внимание, что битовый шаблон для вещественного числа со значением 100.0 не будет (конечно, ) интерпретируется как целое число 100.

И хакерство не останавливается на достигнутом. Одним из эффектов объявления блока COMMON является расположение переменных в памяти, в вашем случае за элементами 10500 (= 100*21*5) блока ASCN следуют элементы 8700 блока FEMPTY2. Немного умножив и сложив, вы обнаружите, что 38400 = 2*(10500+8700) соответствует размеру целого числа по умолчанию в этой программе, равному 4 байтам, то есть половине размера REAL*8, используемых в других переменных. Таким образом, массив KLCKF2D больше, чем ASCN, но первоначальный программист знал, что следующие 17400 байта будут заняты FEMPTY2.

Так что да, это может быть способ установить все биты в этой части данных вашей программы в памяти на 0, но это (сейчас считается) ужасным взломом. Но он должен быть переносимым - последовательные стандарты Fortran были очень консервативны в отношении удаления устаревших функций из языка и авторов компиляторов, тем более, обратная совместимость ОЧЕНЬ важна для программистов Fortran.

О, и, чтобы ответить на ваш вопрос, да, блоки COMMON были (обратите внимание на прошедшее время) способом FORTRAN77 для объявления и использования глобальных переменных. В наши дни язык предлагает гораздо более безопасный вариант объявления переменных для глобального совместного использования, заключая их в MODULE и USE-связывая их.

Я бы не удивился, увидев строчку вроде

COMMON/COMMF2D/KLCKF2D(38400)

в вашем коде блоки COMMON также могут (ab-) использоваться для переименования и повторного ввода мест хранения.

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

person High Performance Mark    schedule 08.08.2012
comment
Спасибо @Марк! Да, я знаю, что EQUIVALENCE — это просто объявление; плохая формулировка с моей стороны. - person Wolfy; 08.08.2012