ФОРТРАН ОБЩИЙ блок инициализации

Новичок на Фортране, меня попросили поработать над старой базой кодов на Фортране, написанной на Фортране 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 это просто подсказки компилятору и не гарантировано)

2 ответа

Решение

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

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

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

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

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

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

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

COMMON/COMMF2D/KLCKF2D(38400)

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

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

Ну, портативная или нет, практика была ... обычным явлением. (Земляной юмор. Орк. Орк.) Я приведу вам пример: данные в исходном коде игры Zork, которую я обновил, - это практически не что иное, как обычные блоки и эквиваленты. https://github.com/LydiaMarieWilliamson/zork-fortran

В соседних переводах C вы увидите, как это разыгрывается в C. Переводчик f2c испытывает трудности с обработкой эквивалентностей и общих блоков (как вы увидите в моем журнале переводов). Мой совет состоит в том, чтобы перекодировать все это на C или C++ и исправить там. Это сделает его более доступным для большего числа программистов. Я готовлюсь сделать это со всем дистрибутивом LAPACK (как вы, возможно, уже заметили) - это от 500000 до 1000000 строк.

Эквивалент C самой структуре также является лучшим способом создания многомерных массивов. Вы выделяете только один базовый сегмент для всего объекта. Затем для второго измерения вы выделяете в него сегмент указателей - растр. Затем для третьего измерения вы выделяете сегмент указателей на это ... и так далее.

Не существует хорошей эквивалентности языка C для самого утверждения эквивалентности. (Земляной юмор. Орк. Орк.) Вместо этого эквивалент эквивалентности лучше всего найти в C++ с использованием ссылочных типов. В C++ вы также можете более напрямую отображать индексы Fortran, поскольку сами индексы (с скобками типа [] и ()) являются программируемым оператором. Таким образом, вы можете напрямую перевести эквивалентную структуру и ее методы индексации как есть - как статическую структуру без необходимости в вышеупомянутом распределении.

Другие вопросы по тегам