Значение INTENT аргументов / переменных в подпрограммах и функциях в Fortran 90 - PullRequest
1 голос
/ 08 августа 2011

У меня есть несколько вопросов о INTENT переменных в подпрограмме на Фортране. Например, несколько недель назад я опубликовал вопрос о другой теме на Фортране ( В Фортране 90, что является хорошим способом записи массива в текстовый файл по строкам? ), и один из ответы включали код для определения команд tick и tock. Я нашел их полезными для запуска моего кода. Я вставил tick и tock ниже и использовал их в простом примере, чтобы рассчитать цикл DO:

MODULE myintenttestsubs

  IMPLICIT NONE

CONTAINS

SUBROUTINE tick(t)
  INTEGER, INTENT(OUT) :: t
  CALL system_clock(t)
END SUBROUTINE tick

! returns time in seconds from now to time described by t
REAL FUNCTION tock(t)
  INTEGER, INTENT(IN) :: t
  INTEGER :: now, clock_rate

  CALL system_clock(now,clock_rate)

  tock = real(now - t)/real(clock_rate)
END FUNCTION tock

END MODULE myintenttestsubs

PROGRAM myintenttest
  USE myintenttestsubs
  IMPLICIT NONE
  INTEGER :: myclock, i, j
  REAL :: mytime

  CALL tick(myclock)

  ! Print alphabet 100 times
  DO i=1,100
     DO j=97,122
        WRITE(*,"(A)",ADVANCE="NO") ACHAR(j)
     END DO
  END DO

  mytime=tock(myclock)
  PRINT *, "Finished in ", mytime, " sec"
END PROGRAM myintenttest

Это приводит к моему первому вопросу о INTENT (мой второй вопрос, ниже, касается подпрограмм или аргументов / переменных функций, для которых INTENT не явно указан):

  1. Чтобы запустить таймер, я пишу CALL tick(myclock), где myclock - целое число. Заголовок подпрограммы - SUBROUTINE tick(t), поэтому он принимает фиктивное целое число t в качестве аргумента. Однако внутри подпрограммы t задано INTENT (OUT): INTEGER, INTENT(OUT) :: t. Как это может быть? Мое наивное предположение состоит в том, что INTENT (OUT) означает, что значение этой переменной может быть изменено и будет экспортировано из подпрограммы - и не считывается. Но ясно, что t читается в подпрограмма; Я передаю целое число myclock в подпрограмму. Так как t объявлено как INTENT (OUT), как может случиться так, что t, кажется, также прибывает в ?

  2. Я заметил, что в функции tock(t) целочисленные переменные now и clock_rate не имеют явно заданных значений INTENT. Тогда каков охват этих переменных? now и clock_rate только видны внутри функции? (Вроде как INTENT (NONE) или INTENT (LOCAL), хотя такого синтаксиса нет?) И, хотя это функция, верно ли то же самое для подпрограмм? Иногда, когда я пишу подпрограммы, я хотел бы объявить «временные» переменные, подобные этой, - переменные, которые видны только внутри подпрограммы (например, для изменения ввода на шаге, предшествующем назначению окончательного результата). Это то, что достигается отсутствием указанного INTENT?

Я просмотрел текст (текст Fortran 90 от Hahn ) и в нем он дает следующее краткое описание намерения аргумента:

Намерение аргумента. Пустые аргументы могут быть указаны с помощью intent атрибут, то есть намерены ли вы использовать их в качестве входных данных, или вывод, или оба, например

SUBROUTINE PLUNK(X, Y, Z)
REAL, INTENT(IN) :: X
REAL, INTENT(OUT) :: Y
REAL, INTENT(INOUT) :: Z
...

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

Если целью является OUT, соответствующий фактический аргумент должен быть переменная. Вызов, такой как

CALL PLUNK (A, (B), C)

приведет к ошибке компилятора - (B) - это выражение, а не переменная.

Если намерение INOUT, соответствующий фактический аргумент должен снова быть переменной.

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

Рекомендуется указывать все фиктивные аргументы. В В частности, все аргументы функции должны иметь намерение IN. Намерение может также указывается в отдельном утверждении, например, НАМЕРЕНИЕ (ВХОД) X, Y, Z.

В приведенном выше тексте даже не упоминается аргумент / переменная scope ; похоже, в основном речь идет о том, можно ли изменить аргумент / переменную значение внутри подпрограммы или функции. Верно ли это, и если да, что я могу предположить о сфере действия в отношении INTENT?

Ответы [ 3 ]

3 голосов
/ 09 августа 2011

Вы в основном правы относительно намерения, но ошибаетесь в отношении семантики tick (). Тик рутина

SUBROUTINE tick(t)
  INTEGER, INTENT(OUT) :: t
  CALL system_clock(t)
END SUBROUTINE tick

выводит значение; намерение, которое передается, является значением системных часов во время вызова подпрограммы. Затем tock () использует это значение для вычисления прошедшего времени, взяв это время как input и сравнив его с текущим значением system_clock:

REAL FUNCTION tock(t)
  INTEGER, INTENT(IN) :: t
  INTEGER :: now, clock_rate

  CALL system_clock(now,clock_rate)

  tock = real(now - t)/real(clock_rate)
END FUNCTION tock

Что касается области действия: intent (in) и intent (out) обязательно применяются только к «фиктивным аргументам», переменным, которые передаются в списке аргументов функции или подпрограммы. Например, в приведенных выше примерах переменные локально упоминаются как t, потому что именно так называется соответствующий фиктивный аргумент, но переменная обязательно существует вне этой подпрограммы.

С другой стороны, переменные now и clock_rate являются локальными переменными; они существуют только в рамках этой рутины. У них не может быть предложений intent, поскольку они не могут ни принимать, ни передавать значения; они существуют только в рамках этой рутины.

2 голосов
/ 09 августа 2011

Компиляторы не обязаны обнаруживать все ошибки программиста.Большинство компиляторов обнаружат меньше ошибок по умолчанию и станут более строгими с помощью параметров компиляции.При определенных параметрах компилятор с большей вероятностью обнаружит нарушение намерения аргумента и выведет диагностическое сообщение.Это может помочь в более быстром обнаружении ошибки.

Разница между объявлением отсутствия намерения и намерения (inout) невелика.Если пустышка намерена (inout), фактический аргумент должен быть определим.Одним случаем неопределенного аргумента является константа, такая как «1.0».Нет смысла присваивать константу.Это может быть диагностировано во время компиляции.Если фиктивный аргумент не имеет заданного намерения, фактический аргумент должен быть определим, если он назначен во время выполнения процедуры.Это гораздо сложнее диагностировать, так как это может зависеть от выполнения программы (например, операторов IF).См. намерение Фортрана (inout) против пропущенного намерения

1 голос
/ 09 августа 2011

После быстрого поиска я нашел этот вопрос: В чем явная разница между намерениями Фортрана (вход, выход, выход)?

Из этого я узнал: «Намерения - это всего лишь подсказки для компилятора, и вы можете выбросить эту информацию и нарушить ее». - от Глейзер Гай

Итак, я думаю, что ваш первый вопрос: назначение intent (OUT) только говорит компилятору проверить, действительно ли вы передаете переменную в подпрограмму tick (). Если вы назвали это так:

call tick(10)

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

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

Ваши подпрограммы также могут иметь локальные переменные, которые действуют как временные переменные. Эти переменные не могут иметь намерений. Таким образом, переменные now и clock_rate в вашей подпрограмме tock являются локальными переменными и не должны иметь намерений. Попробуйте дать им намерения и посмотреть, что произойдет, когда вы компилируете. Тот факт, что они не имеют намерений, не означает то же самое, что аргумент без намерения. Эти две переменные являются локальными и известны только подпрограмме. Аргументы без намерения все еще могут использоваться для передачи информации в / из подпрограммы; должно быть намерение по умолчанию, подобное намерению (inout), но у меня нет документации, чтобы доказать это. Если я найду это, я отредактирую этот ответ.

EDIT: Также вы можете захотеть увидеть эту страницу для обсуждения вопросов, возникающих в связи с объявлениями INTENT (OUT). Это сложный сценарий, но я подумал, что это может стоить документирования.

...