2010-05-21 2 views
28

Хорошая практика подсказывает, что аргументы подпрограммы в Fortran должны у каждого есть определенное намерение (т.е. intent(in), intent(out) или intent(inout), как описано this question):Fortran намерения (INOUT) против опуская намерения

subroutine bar (a, b) 
    real, intent(in) :: a 
    real, intent(inout) :: b 
    b = b + a 
    ... 

Однако, не указав намерения действует Fortran:

subroutine bar (a, b) 
    real, intent(in) :: a 
    real :: b 
    b = b + a 
    ... 

есть ли реальные различия вне времени компиляции проверки для заданного аргумента, как intent(inout) и аргумент без указания в палатка? Есть ли что-нибудь, о чем я должен беспокоиться, если я доработаю намерения до более старшего, без намерения, кода?

ответ

20

Согласно Справочник Fortran 2003 от Adams и др., Существует одно отличие между аргументом (inout) и не аргументом без указания намерения. Фактический аргумент (т. Е. В вызывающем) в случае намерения (inout) всегда должен быть определяемым. Если намерение не указано, аргумент должен быть определен , если выполнение подпрограммы пытается определить фиктивный аргумент. Определяемый означает установку значения: dummy_arg = 2.0. Очевидно, что фактический аргумент должен быть переменной, если это сделано. Для намерения (inout) фактический аргумент должен быть определяемым независимо от того, выполняет ли это подпрограмма. Без указанного намерения это зависит от того, что происходит при этом конкретном вызове подпрограммы - если подпрограмма не определяет переменную, это нормально; если это так, то есть проблема - такие случаи, как запись в фактический аргумент, который является константой, будут, очевидно, вызывать проблемы.

Это не означает, что компилятор будет диагностировать все эти случаи - то, что стандарт требует, чтобы компилятор диагностировал, является другой проблемой. В момент компиляции было бы почти невозможно обнаружить все ошибки требования, не указанные в запросе, поскольку нарушения зависят от потока времени выполнения кода. Компилятору гораздо проще диагностировать случай намерения (inout) и предупреждать вас о проблемах с кодом.

5

Ваш вопрос подсказывает мне, что вы можете столкнуться с различием в поведении, если ваш код передает PARAMETER в качестве фактического аргумента, который ваша подпрограмма затем пытается записать. Без объявления INTENT компилятор может отпустить это, что приведет к нечетному поведению. С объявлением я ожидаю ошибку времени компиляции.

Вы и я можем подумать, что нет никакой разницы между INOUT и объявлением INTENT, но не забывайте, что существует много старых программ Fortran и что совместимость со старыми языковыми версиями является важной особенностью новых стандарты. Если это было правильно (но изворотливое) FORTRAN77, то многие люди ожидают, что их код останется верным (все еще изворотливым) с помощью компилятора Fortran 90+.

Быстрое считывание стандарта 2003 указывает на то, что существует разница между INOUT и INTENT, но требуется более точное считывание. Если вы проверите это, дайте нам знать ваши выводы; если у меня будет время позже, я испытаю это сам и дам вам знать.

+3

Я построил четыре тестовых примера, пытающихся изменить параметр в подпрограмме. Два теста с внешними подпрограммами - т. Е. В файле сами по себе - с и без намерения (inout). Компилятор не жалуется ни на один из них. Это не неожиданность (без интерфейса) и возникающие exe segfaults. Я запустил подпрограмму в модуле для последних двух тестов и посмотрел segfault для случая без намерения и ошибки компилятора («Фактический аргумент в (1) должен быть определен, поскольку фиктивный аргумент« b »- INTENT = OUT/INOUT ") с интерфейсом. Это с gfortran 4.4.4-2 от дебианской системы. –

+0

Отлично, мы оба кое-чему научились. –

+1

В эти дни параметры помещаются в отмеченную только для чтения часть памяти, но это не всегда было правдой. Известным примером в очень старых компиляторах было переопределение числовых констант http://coding.derkeiler.com/Archive/Fortran/comp.lang.fortran/2005-01/0485.html –

3

Чтобы понять роль намерения в/из, вам необходимо знать, что внутри, Fortran эффективно передает переменные по ссылке. Это не всегда совпадает с фактическим передачей по ссылке.

Если вы передадите внутреннюю часть 2-мерного массива подпрограмме, то есть: data(i1:i2, j1:j2), то Fortran копирует эти данные в непрерывный раздел памяти и передает новый адрес в подпрограмму. По возвращении данные копируются обратно в исходное местоположение.

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

Он не только действует как защитный механизм для изменения данных, которые вы хотите сохранить без изменений, но также может ускорить работу вашего кода при работе с большими наборами данных.

Смежные вопросы