История развития программного обеспечения

О бедном Фортране

О бедном Фортране[1]...

На вопрос: "На каком языке написана эта программа?"

write (*,*) ‘Hello, World!’
end

не каждый сразу ответит, что на Фортране-77. Для многих из тех, кто видел Фортран-IV ЕС и СМ ЭВМ, Фортран-77 в реализации для ПЭВМ покажется белым лебедем, в которого превратился когда-то популярный гадкий утенок. Этот стереотип настолько силен, что, говоря о выборе языка программирования для той или иной задачи, программисты называют Си/С++, Паскаль, Модулу-2, Бейсик, реже Smalltalk и Форт и как-то морщатся при упоминании о Фортране, считая его архаичным и примитивным. Автор и сам разделял эту точку зрения, пока случайно не познакомился с Мiсrоsoft FORTRAN версии 5.0 для IВМ РС/ХТ/АТ и РS/2 [1-2] (далее MS-Фортран).

Его отличия от Фортрана-IV можно разделить на три группы:

  • новые типы данных;
  • новые конструкции языка;
  • улучшение ввода-вывода.

Новые типы данных

Первое, что порадовало, это возможность записывать константы в любой системе счисления от двоичной до 36-ричной, например:

J=2#11111001  ! двоичная константа

или (то же самое):

J=16#FC  !16-ричная константа

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

Другой интересный объект – это строки, которые могут быть длиной от 1 до 32767 знаков. Строки задаются одним из следующих операторов:

Character *LL имя  ! Здесь LL – длина строки,
Character имя *LL   ! имя – список имён переменных
Character * (*) имя  ! и/или массивов
Character имя * (*)  ! Например:
Character имя (const*LL)  ! Character*8 My_string, Msg

и ограничиваются как одинарными, так и двойными кавычками. Строки могут сформироваться по правилам языка Си, т. е. заканчиваться нулем, а внутри себя содержать непечатаемые символы, которые задаются с помощью обратной косой черты, например, известное всем \n – новая строка. Чтобы отличить строки, совместимые с Си, от обычных, в конце них ставят латинскую букву С:

'/n Текст сообщения 'C

Так как в М8-Фортране нет пустой строки, то использование '' недопустимо, а ''С – допустимо (это строка длиной 1, содержащая нуль). Подстрока задается как элемент массива указанием её первого и последнего индексов. Если

new_name = ‘123456789’

то

new_name (4:8)  ! это подстрока ‘45678’

Если один из индексов опущен, то предполагается индекс первого или последнего элемента соответственно. Так, выполнение

F_Name= ‘kingwi’
Write (*,*) F_Name(4:), F_Name(:2)

выведет на экран слово wiking. Для операции конкатенации строк используется знак //, а не привычный всем +.

Из современных конструкций для представления сложных типов данных в язык введены структуры, массивы структур и объединения:

Structure /str_name/
character*25 city
integer*4 post_index

End Structure

Подобным образом вводится структурный тип данных. Переменная или массив этого типа объявляется в операторе

record /str_name/ city_list(100), city_var

Обращение к элементу структуры осуществляется, как обычно, путем указания полного имени, например:

city_list(42).post_index=123060

И, наконец, структуры могут быть вложенными.

Более сложным образом в язык введены объединения – UNION. Для этого создана конструкция, именуемая МАР, которая объявляет компилятору, что перечисленные в ней данные (переменные, массивы и структуры) располагаются в памяти последовательно, в том порядке, как они указаны:

MAP
integer*2 jk,jl,jq
character*12 what
END MAP

Конструкции МАР используются далее в UNION, чтобы задать совмещение по памяти данных более удобно, чем это делается с помощью оператора EQUIVALENCE:

UNION
MAP
integer*4 loopcnt, newstep
END MAP
MAP
character*10 descr
END MAP

END UNION

Здесь переменная descr располагается в памяти с того же адреса, что и loopcnt.

Индексы массивов теперь могут задаваться, как в Си.

Наиболее неожиданной возможностью в М8-Фортране является динамическое распределение памяти под массивы, отсутствие которого било бичом Фортрана-IV. Для динамических массивов при их объявлении указывается атрибут ALLOCTABLE и используются операторы аllосаtе и dealloсаtе соответственно для распределения памяти под массив и её освобождения. Например:

integer*2 SoundW [ALLOCTABLE, HUGE] (:,:,:) integer speed,N,M,Error
….
ввод значений speed, N, M и проверка их допустимости
….
allocate (SoundW(speed,N,M), STST=Error)
if Error .NE. 0 then Stop ‘Не хватает памяти…’
…   ! вычисления
end
subroutine subprim(speed,N,M,iS)
integer iS[HUGE] (1)

end

При этом массив может занимать более 64 Кбайт ОЗУ (атрибут HUGE). Если он не указан, а динамически распределяется память более 64 Кбайт, то это вызывает зависание программы.

Динамические массивы позволяют:

  • не использовать в целях экономии памяти один и тот же массив в разных целях, что плохо во всех отношениях;
  • не задавать жестко размерность решаемой задачи;
  • значительно уменьшить размер ЕХЕ-файла (на объем статических массивов).

Заметим, что в отличие от Си и Паскаля в Фортране-77 нет необходимости возиться с указателями.

Раньше во многих реализациях Фортрана-IV, если у имени массива не указывался индекс, то подразумевался первый элемент массива. В МS-Фортране подразумевается действие, выполняемое над всеми элементами массива, которое называется выражением над массивом (к сожалению, вышесказанное не относится к динамическим массивам). Все встроенные функции, имеющие скалярные аргументы, могут иметь и аргумент в виде массива.

Выражения над массивами позволяют:

  • сэкономить около 30 байт кода на каждом цикле;
  • ускорить примерно на шесть машинных команд работу с каждым элементом массива.

Примеры.

ZeroArr=0  ! Присваивание константы каждому элементу массива
Arr2=-Arr1  ! Присваивание элемента с обратным знаком
Arr3= Sin(Arr2)  ! Применение функции к каждому элементу массива
Arr4=Arr3-Arr1(22)  ! Вычитание элемента Arr1(22) из каждого элемента массива Arr3
LogArr = .NOT. LogArr2  ! Работа с массивами типа logical

Новые конструкции языка

В Фортране-77 (и соответственно в МS-Фортране) новые конструкции обеспечивают возможность писать без меток и операторов GOTO. Прежде всего это касается циклов:

Цикл DO

do exp1, exp2 [,exp3]
…. тело цикла…
end do

Цикл DO WHILE

do while exp1
…. тело цикла…
end do

Хотя из тела цикла можно выходить с помощью GОТО, существуют два оператора, позволяющие сделать это более структурно:

  • оператор CYCLE передает управление на последний оператор цикла (т. е. осуществляет переход к следующему шагу цикла);
  • оператор EXIT передает управление на первый оператор после конца цикла (т.е. выходит из цикла).

Введена Си-подобная конструкция выбора из альтернатив, очевидная из примера:

character*1 cmd
select case (cmd)
case (‘r’,’R’)
call readfrom
case (‘1’:‘8’)
call findkey(cmd)
case (‘A’:’J’, ‘a’:’j’)
write (*,*) ‘Not a Command’
case default
call monitor (cmd)
end select

Конструкция IF также стала более привычной:

if expr1 then
….  ! операторы
end if

либо, в более сложной форме:

if
else if

else
end if

Файлы прямого и последовательного доступа по структуре делятся на форматные, неформатные и двоичные.

FORM = ‘BINARY
‘FORMATTED’
‘UNFORMATTED’

Так как часто возникает проблема стыковки различных программ, то данные всегда могут быть в виде ASCII-файла (FORMATTED), но при больших размерах массивов это неудобно. UNFORMATTED-файлы содержат, к сожалению, дополнительную фортрановскую информацию, которую приходится удалять при передаче программе, например на Турбо-Паскале. BINARY-файлы хранят машинное представление данных и поэтому наиболее компактны.

Отметим, что графические возможности МS-Фортрана и МS-Си совпадают, а программы на МS-Фортране выполняются в среднем на 20% быстрее, чем аналогичные на Турбо-Си 2.0.

Заключение

Летом 1991 г. фирма Microsoft выпустила MS-Fortran 5.1, для которого была разработана интегрированная оболочка, облегчена компоновка с библиотекой графических подпрограмм и сделано многое другое.

Возникает законный вопрос: так можно ли писать программы на таком Фортране? Конечно, можно! Только осторожно. Ведь все его "ошибки молодости" (отсутствие строгой типизации имен, разделителей между лексемами и т. д.) остались в нём для совместимости с предыдущими версиями. Требование совместимости, вообще говоря, гарантирует консерватизм языка программирования, т. е. является женским началом. С другой стороны, поглощение языком всё новых конструкций должно быть весьма и весьма обоснованным, и здесь следует избегать всеядности Бейсика. Так велика ли, в конце концов, разница между современными Паскалем, Си, Фортраном и другими процедурными языками? С более общих позиций автор называет этот процесс сближения стремлением процедурных языков к их концептуальному идеалу.

Примечания

1. “О бедном Фортране замолвите слово” – строка из старинного программистского романса. – Прим. автора.

Литература

  1. Microsoft FORTRAN Reference. Version 5.0 for MS OS/2 and MS-DOS Operating Systems. – USA: Microsoft Corp. 1989. – 524 pp.
  2. Велецки Я. Фортран–77: Пер. с польск. – М.: Высшая школа, 1991. 207 с.

Статья опубликована в сборнике БИТ, вып. 4. – М.: ИнфоАрт, 1992 г.