2013-01-07 2 views
3

Я пытаюсь расшифровать код fortran. Он передает указатель на функцию как фактический аргумент, а формальный аргумент - цель. Он определяет и выделяет указатель типа GlobalData в основной программе, то она вызывает функцию передачи этого указателя:Функция Fortran: указатель как фактический аргумент и цель как формальный

module dataGLOBAL 
type globalDATA 
    type (gl_1)  , pointer :: gl1 
    type (gd_2)  , pointer :: gd2 
    type (gdt_ok) , pointer :: gdtok 
    ... 
    ... 
end type globalDATA 
end module dataGLOBAL 


Program main 
.... 
.... 
use dataGLOBAL 
... 
type(globalDATA),pointer :: GD 

allocate(GD) 
returnvalue = INIT(GD) 
.... 
.... 
end 

Функция читает:

integer function INIT(GD) result(returnvalue) 
.... 
.... 
use dataGLOBAL 

type(globalDATA) , target :: GD 

allocate (GD%gl1) 
allocate (GD%gd2) 
allocate (GD%gdtok) 
.... 
.... 
end function INIT 

Какой смысл делать это? И почему нужно выделять как указатель в основной программе, так и отдельные компоненты целевой структуры? благодаря А.

ответ

9

Несколько вещей, которые могут вступить в игру ...

  • Когда вы предоставляете указатель в качестве фактического аргумента процедуры, где соответствующий фиктивный аргумент не имеет атрибут POINTER (в данном случае), то, что связано с аргументом фиктивного объекта, является целью фактического указателя аргумента. Итак, в этом случае передаваемая вещь - это объект, который указывает GD (в основной программе) - вещь, которая была выделена оператором allocate. (Если и фактический, и фиктивный аргументы имеют аргумент POINTER, тогда сам POINTER «передается» - вы можете изменить то, что указывает POINTER, и это изменение отражается обратно в области вызова.)

  • Поскольку GD фиктивный аргумент внутри функции имеет целевой атрибут, указатели внутри функции могут быть указаны на фиктивном аргументе. Вы не показываете деклараций для таких указателей, но, возможно, они находятся в выпущенном коде. Если ничего никогда не указывал на фиктивный аргумент GD (в том числе и внутри любых процедур, которые могут быть вызваны функцией INIT), атрибут TARGET является излишним, но безвредным, кроме запрета некоторых оптимизаций.

  • Вещи, у которых есть атрибут указателя, также (автоматически по языковым правилам) имеют атрибут TARGET - поэтому GD в основной программе имеет атрибут TARGET. Тот факт, что GD в основной программе и в функции BOTH имеет целевой атрибут, может быть релевантным, потому что ...

  • Когда аргумент фиктивного атрибута имеет атрибут TARGET, а предмет, переданный в качестве фактического аргумента, имеет атрибут TARGET, то указатели, связанные с фиктивным аргументом внутри процедуры, также «обычно» (есть исключения/зависимости процессора для коиндексированных вещей/несмежных массивов/секторов с индексом, слишком сложных для меня, чтобы запомнить), связанных с соответствующим фактическим аргументом. Если указатель не является локальной переменной (возможно, это указатель, объявленный в модуле), то эта связь сохраняется после завершения процедуры. Возможно, это актуально в коде, выпущенном. (В качестве альтернативы, если фактический аргумент не имеет атрибута TARGET, тогда любые указатели, связанные с аргументом фиктивного типа, становятся неопределенными, когда процедура заканчивается.)

  • Компоненты типа globalDATA сами являются указателями. Следовательно, GD в основной программе является указателем на что-то (что-то выделяется одним оператором ALLOCATE в основной программе), который сам содержит указатели на другие вещи (эти другие вещи выделяются многочисленными операторами ALLOCATE в функции). У вас есть два уровня указателя, следовательно, два уровня ALLOCATE.

  • Перед тем, как Fortran 2003 (или Fortran 95 с «allocatable TR»), вы не могли бы иметь компоненты ALLOCATABLE в производных типах, и вы не могли бы иметь ДОПОЛНИТЕЛЬНЫЕ фиктивные аргументы - когда возникла необходимость в динамическом размещении с этими прежними вам пришлось использовать указатели вместо этого, даже если вы использовали указатели как значения. Я сильно подозреваю, что ваш код датируется этой эрой (поддержка распределяемого ТР получила широкое распространение примерно десять лет назад). В очень «современных» указателях Fortran (следует?) Используется только тогда, когда вам понадобятся переменные, указывающие на другие вещи (где другие вещи включают «нет»).

+0

Спасибо. Теперь все ясно! – Lupocci

+0

Для пункта 4, когда оба фиктивного и фактического аргумента являются TARGET: ассоциация указателей гарантированно выйдет за конец процедуры, если фиктивный аргумент объявлен с предполагаемой формой 'a (:)', но не если он объявлен с явным размером 'a (5)' или предполагаемый размер 'a (*)' [Modern Fortran - стиль и использование] (https://books.google.nl/books?id=5Qj2DieTHsYC&lpg=PA69&dq=fortran%20target%20pointer%20scope&pg= PA71 # v = OnePage & д & е = ложь) – Frepa

2

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

+1

Хорошо спасибо, я понимаю, что вам нужно выделить как общую переменную, так и указатели компонентов. Но я не мог найти в своем руководстве fortran 95 или в Интернете какое-либо упоминание о возможности того, что указатель является фактическим аргументом, а цель - формальной. Является ли это законным? Какая разница, если бы формальный был объявлен как указатель вместо цели? спасибо – Lupocci

0

Поскольку атрибут указателя не указан для фиктивного аргумента, весь полученный тип GD передается от основного кода (а не указатель на него). На стороне подпрограммы вы можете явно написать

integer function INIT(GD) result(returnvalue) 
... 
use dataGLOBAL 

type(globalDATA), intent(inout), target :: GD 

, чтобы сделать его более понятным. Атрибут target фиктивного аргумента только гарантирует, что вы можете указать на этот аргумент внутри подпрограмму через назначение указателя.

До тех пор, пока вы обрабатываете только поля производного типа, но не производного типа в целом (например, путем выделения или освобождения от него) указатель или сам производный тип.

Как уже отмечалось в других ответах, цель программы, по-видимому, отделяет распределение производного типа и его компонентов друг от друга. Одним из возможных преимуществ этой стратегии является возможность передачи как указателей, так и статически распределенных производных типов в процедуру INIT.

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