2013-01-07 14 views
3

我想解密fortran代碼。它將一個指向函數的指針作爲實際參數傳遞,而形式參數則是一個目標。它定義並在主程序分配型全球國際的指針,然後調用一個函數傳遞一個指針: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

有幾件事情可能會發揮作用......

  • 當你(這裏的情況)提供一個指針作爲實際參數傳遞給一個過程,其中相應的啞參不具有指針屬性,與僞參數關聯的東西是實際參數指針的目標。所以在這種情況下,被傳遞的東西是GD(在主程序中)指向的對象 - 分配語句分配的東西。 (當實際參數和虛擬參數都具有POINTER參數時,POINTER本身是「通過」的 - 您可以更改POINTER指向的內容並將該更改反映回調用範圍。)

  • 因爲GD函數內部的僞參數具有目標屬性,函數內的指針可以指向僞參數。你不會顯示這樣的指針的任何聲明,但也許它們在被遺忘的代碼中。如果沒有任何指令指向GD虛假參數(包括可能由INIT函數調用的任何過程內部),那麼TARGET屬性是多餘的,但除了禁止某些優化之外無害。

  • 具有指針屬性的東西(通過語言規則自動)也具有TARGET屬性 - 因此主程序中的GD具有TARGET屬性。 GD在主程序和函數BOTH中具有目標屬性的事實可能是相關的,因爲...

  • 當虛擬參數具有TARGET屬性並且由於實際參數具有TARGET屬性而傳遞的東西時,那麼與過程內的僞參數相關聯的指針也與相應的實際參數相關聯,也是「通常」(對於索引的東西/不連續的數組/矢量下標的部分,我記住的東西有異常/處理器依賴關係)。如果一個指針不是一個局部變量(也許它是一個在模塊中聲明的指針),那麼這個關聯在過程結束之前仍然存在。也許這在消失的代碼中是相關的。 (或者,如果實際參數不具有TARGET屬性,則在過程結束時,與該僞參數關聯的任何指針都將變爲未定義。)

  • globalDATA類型的組件本身是指針。因此,主程序中的GD是一個指向某些東西的指針(即由主程序中的單個ALLOCATE語句分配的東西),它本身包含指向其他東西(其他東西由函數中的衆多ALLOCATE語句分配的東西)的指針。你有兩個級別的指針,因此有兩個級別的ALLOCATE。

  • 在Fortran 2003(或帶有「可分配TR」的Fortran 95)之前,您不能在派生類型中擁有ALLOCATABLE組件,並且您不能擁有ALLOCATABLE虛擬參數 - 當需要動態分配時與這些前者相沖突即使你只使用指針作爲值,你必須改用指針來限制。我強烈懷疑你的代碼來自這個時代(支持可分配的TR在十年前已經廣泛流行)。在非常「現代」的Fortran指針中,(只有?)只有當你可能需要指向其他事物的變量時(其他事物包括「無事物」),纔會使用它。

+0

謝謝。現在一切都很清楚! – Lupocci

+0

對於第4點,當虛擬參數和實際參數都是TARGET時:如果僞參數聲明爲具有假定的形狀'a(:)',但如果聲明的是具有顯式大小的聲明,則指針關聯保證在該例程結束時存活'a(5)'或假定的大小'a(*)'[Modern Fortran - Style and Usage](https://books.google.nl/books?id=5Qj2DieTHsYC&lpg=PA69&dq=fortran%20target%20pointer%20scope&pg= PA71#v = onepage q&&F =假) – Frepa

2

使用指針變量是一個用戶自定義類型,它本身包含指針,您必須分配(即創建存儲)整體變量和組件指針。當整體變量爲時,組件不會自動分配。有人提出了一個設計選擇,將主程序中的整體變量和子程序中的組件分配。也許他們認爲分配整體變量很簡單,但分配所有組件變得複雜,並想將其分解爲子例程。

+1

好的謝謝,我明白你必須分配整體變量和組件指針。但我無法在我的fortran 95手冊或網上找到任何提及指針是實際參數而目標是正式的可能性。這是否合法?如果將形式聲明爲指針而不是目標,會有什麼區別? 謝謝 – Lupocci

0

因爲沒有爲僞參數中指定的指針屬性,則整個派生類型GD從主碼(不是指向它的指針)通過。在子程序方面,你可以明確地寫出

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

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

使其更清楚。僞參數的目標屬性只能確保您可以通過指針分配指向該參數裏面的子例程。

只要您只操作派生類型的字段,而不是派生類型的整體(例如通過分配或取消分配),它應該沒有什麼區別,無論您是通過傳遞一個INIT例程指針或派生類型本身。

正如在其他答案中已經指出的那樣,程序的目的似乎是將派生類型及其組件彼此分配。這種策略的一個可能的優點是可以將0123,例程的指針和靜態分配派生類型都傳遞給它。