Синтаксис: формат, комментарии, структура программы
Свободный формат, комментарии, продолжение строк и структура программной единицы — грамматика, на которой написан весь современный Fortran.
Свободный формат (free form) — режим записи кода Fortran, где операторы располагаются в строке без привязки к номерам колонок; принят начиная с Fortran 90 и используется во всех новых программах.
Прежде чем писать содержательные программы, нужно освоить «правила правописания» языка: как разбивать строки, где ставить комментарии, чем разделять операторы и из каких частей состоит программная единица. В Fortran эти правила несут на себе отпечаток истории, и понимание этого отпечатка избавит вас от загадочных ошибок при чтении старого кода. Этот урок — про синтаксический скелет, на который мы будем наращивать мясо в следующих разделах.
Два формата: фиксированный и свободный
Исторически Fortran писали в фиксированном формате (fixed form), унаследованном от перфокарт. Каждая строка делилась на жёсткие зоны: колонки 1–5 — метки, колонка 6 — признак продолжения, колонки 7–72 — собственно код, остальное игнорировалось. Буква C или звёздочка в первой колонке означала комментарий. Этот формат всё ещё встречается в файлах .f и .for, и его надо узнавать в лицо.
Современный код пишут в свободном формате, который активируется расширением файла .f90 (и новее). Здесь нет магических колонок: оператор начинается где угодно, отступы — на ваше усмотрение, строка может быть длиной до 132 символов. Весь наш курс — свободный формат. Сравните одну и ту же мысль в двух стилях, чтобы прочувствовать разницу.
! Свободный формат (.f90) — современный
program area
implicit none
real :: r, s
r = 2.0
s = 3.14159 * r**2
print *, "Площадь круга:", s
end program area
Здесь восклицательный знак ! открывает комментарий, который тянется до конца строки, — это универсальный синтаксис комментариев в свободном формате, работающий в любом месте строки, а не только в начале.
Структура программной единицы
Любая исполняемая программа на Fortran состоит из главной программной единицы (program) и, возможно, дополнительных единиц — процедур и модулей, которые мы изучим позже. Главная единица имеет строго заданный каркас, и порядок частей в нём важен.
program demo ! 1. заголовок: program + имя
implicit none ! 2. начало раздела описаний
integer :: n ! объявления переменных и констант
real :: x
n = 5 ! 3. исполняемый раздел: операторы
x = real(n) / 2.0
print *, x
end program demo ! 4. конец единицы
Раздел делится на две части. Сначала идёт раздел описаний: implicit none, объявления переменных, констант, типов. Затем — исполняемый раздел с операторами, которые выполняются по порядку. Смешивать их нельзя: нельзя объявить переменную после первого присваивания. Это отличает Fortran от языков, где объявления разрешены где угодно. Имя в end program demo необязательно, но указывать его — хороший тон: компилятор проверит, что вы закрываете именно ту единицу.
Продолжение длинных строк: символ &
Рано или поздно оператор перестаёт помещаться в одну строку. В свободном формате перенос делается амперсандом & в конце строки: он сообщает компилятору, что оператор продолжается на следующей. Это одна из частых причин ошибок у новичков, поэтому разберём внимательно.
program continuation
implicit none
real :: total
total = 1.0 + 2.0 + 3.0 + &
4.0 + 5.0 + 6.0
print *, "Сумма:", total
end program continuation
Вывод:
Сумма: 21.0000000
Амперсанд в конце первой строки «склеивает» её со второй. Если внутри переноса разрывается строковый литерал или имя, амперсанд ставят с обеих сторон разрыва — и в конце первой строки, и в начале продолжения. Но в обычных арифметических выражениях достаточно одного & в конце. Запомните: амперсанд должен быть последним непробельным символом строки; если после него идёт что-то, кроме комментария, это ошибка.
Несколько операторов в строке и регистр
Иногда хочется записать несколько коротких операторов на одной строке. Разделитель — точка с запятой ;. Злоупотреблять этим не стоит, но для пары связанных присваиваний это уместно.
program multi
implicit none
integer :: a, b, t
a = 3; b = 7
t = a; a = b; b = t ! обмен значениями через временную
print *, a, b
end program multi
Вывод:
7 3
Отдельно подчеркнём то, что шокирует пришедших из C: Fortran не различает регистр букв в именах и ключевых словах. Program, PROGRAM и program эквивалентны; переменные Temperature и temperature — одна и та же. Это значит, что вы не можете завести две переменные, отличающиеся только регистром. Распространённое соглашение — писать ключевые слова строчными, а длинные имена в стиле snake_case или с заглавными буквами для читаемости, помня, что для компилятора это лишь оформление.
Свободная форма и человеческая читаемость
Свободный формат — это не только освобождение от колонок, но и приглашение к аккуратному оформлению. В фиксированном формате отступы были запрещены (код жил строго с 7-й колонки), и старые программы выглядели плоской «лестницей» без структуры. Свободная форма позволяет выделять вложенность отступами, как принято в современных языках, и опытные инженеры этим пользуются: тело цикла или ветки if сдвигают вправо, чтобы структура читалась с одного взгляда. Компилятор отступы игнорирует — они существуют исключительно для человека, — но именно человек тратит на чтение кода в разы больше времени, чем на написание. В научных группах, где код переживает многих авторов и десятки лет, читаемое оформление — не косметика, а вопрос выживаемости проекта.
Ещё одна практическая деталь свободной формы — длина строки. Стандарт допускает строки до 132 символов, но многие команды по соглашению ограничиваются 80, чтобы код помещался в окне терминала и в side-by-side diff при code review. Когда выражение упирается в этот предел, на сцену выходит уже знакомый нам амперсанд продолжения. Привычка переносить длинные формулы по & с осмысленными точками разрыва (например, перед знаком + или *) делает многострочную математику читаемой, тогда как механический перенос «по достижении края» превращает формулу в кашу. Это тот случай, когда мелкая дисциплина оформления заметно влияет на надёжность.
Чувствительность к регистру в широком контексте
Нечувствительность к регистру — историческое решение, и у него есть оборотная сторона, важная при связывании с другими языками. Внутри Fortran MaxValue и maxvalue — одно имя, но когда такая процедура попадает в объектный файл, компилятор фиксирует её имя в каком-то конкретном регистре (обычно нижнем) и, возможно, добавляет подчёркивания. Код на C, чувствительный к регистру, должен обращаться к ней по этому точному имени. Именно поэтому в межъязыковом интерфейсе используют явное указание имени через bind(c, name=...), о котором речь в четвёртом уроке, — оно убирает всякую двусмысленность. Внутри же чисто фортрановского проекта о регистре можно почти не думать, но стоит выбрать единый стиль и держаться его: разнобой вроде Mass в одном месте и mass в другом сбивает читателя, хотя компилятору безразличен.
Как работает под капотом
Почему вообще существует это деление на форматы и зачем амперсанд? Ответ — в истории физического носителя. Перфокарта вмещала ровно 80 колонок; колонки 73–80 отводились под порядковый номер карты, чтобы рассыпавшуюся колоду можно было собрать обратно. Отсюда и предел в 72 колонки для кода, и колонка продолжения. Свободный формат избавил язык от этих ограничений, но компилятор по-прежнему должен отличать конец оператора от его продолжения — в C для этого служит точка с запятой в конце каждого оператора, а Fortran выбрал противоположную логику: оператор по умолчанию заканчивается концом строки, а чтобы продолжить — нужен явный знак &.
Лексический анализатор компилятора, встретив & на конце строки, не завершает текущий оператор, а «дочитывает» следующую строку, склеивая токены. Комментарий ! вырезается ещё раньше, на стадии предобработки строки, поэтому он может стоять и после кода, и после амперсанда — но не между амперсандом и концом строки в роли «продолжения».
Любопытно сравнить философию завершения операторов в разных языках. C, Java, JavaScript требуют точку с запятой в конце каждого оператора — конец строки для них незначим. Python, наоборот, придаёт концу строки смысл и продолжает строку либо неявно (внутри скобок), либо через обратную косую черту. Fortran ближе к Python: конец строки завершает оператор, а явный знак нужен для продолжения. Каждый подход — компромисс между «шумом» лишних символов и риском незаметной ошибки переноса. Зная, к какому лагерю принадлежит язык, вы избегаете машинального переноса строк из чужих привычек.
Частые ошибки
- Объявление переменной в исполняемом разделе. Все
integer ::,real ::и прочие описания обязаны идти до первого исполняемого оператора. Компилятор выдаст ошибку, если нарушить порядок. - Забытый амперсанд при переносе. Если длинное выражение просто перенести на новую строку без
&, компилятор сочтёт это двумя отдельными (и неверными) операторами. - Символ продолжения не последний. Любой непробельный символ после
&(кроме начала комментария) ломает перенос. - Смешение форматов. Попытка скомпилировать код в стиле перфокарт как
.f90приводит к загадочным ошибкам — следите за расширением файла и стилем. - Расчёт на регистр. Две «разные» переменные
xиX— это одна переменная; такой код ведёт себя не так, как ожидает программист из C.
Итоги
- Современный Fortran пишут в свободном формате (файлы .f90); фиксированный формат — наследие перфокарт.
- Комментарий открывается
!и тянется до конца строки в любом месте. - Программная единица состоит из заголовка, раздела описаний и исполняемого раздела — именно в этом порядке.
- Длинные строки переносят амперсандом
&в конце; он должен быть последним непробельным символом. - Несколько операторов в строке разделяют точкой с запятой
;. - Имена и ключевые слова нечувствительны к регистру — закладывайте это в свои соглашения об именовании.