2010-05-21 81 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

根據Adams等人的Fortran 2003 Handbook,在沒有指定意圖的意圖(inout)參數和參數之間存在一個區別。意圖(inout)情況下的實際參數(即在調用者中)必須始終可定義。如果未指定意圖,則參數必須可定義如果子例程的執行嘗試定義僞參數。 可定義表示設置值:dummy_arg = 2.0。顯然,如果這樣做了,實際的論點應該是一個變量。對於intent(inout),實際的參數必須是可定義的,不管子程序是否這樣做。如果沒有指定意圖,它取決於該子例程的特定調用發生了什麼 - 如果該子例程沒有定義該變量,則它是OK的;如果它確實存在問題,那麼寫入一個常量的實際參數等情況顯然會導致問題。

這並不意味着編譯器會診斷所有這些情況 - 標準要求編譯器進行診斷的是一個不同的問題。在編譯時,幾乎不可能檢測到意圖 - 未指定的情況要求的所有錯誤,因爲違反取決於代碼的運行時流程。編譯器診斷意圖(inout)的情況要容易得多,並警告你有關代碼的問題。

5

您的問題提示我想知道(如果您的代碼將PARAMETER作爲您的子程序嘗試寫入的實際參數傳遞給您的參數,您是否會遇到行爲上的差異)。如果沒有INTENT聲明,編譯器可能會放棄它,導致奇怪的行爲。隨着聲明,我期望編譯時錯誤。

你和我可能會認爲INOUT和沒有INTENT聲明沒有什麼區別,但不要忘記有很多舊的Fortran程序,並且與舊版本的兼容性是新的重要特性標準。如果FORTRAN77正確(但不妥協),那麼很多人都希望他們的代碼能夠通過Fortran 90+編譯器保持正確(仍然很狡猾)。

2003標準的快速閱讀確實表明INOUT與無INTENT之間存在差異,但需要更仔細的閱讀。如果你測試了這個,讓我們知道你的結論;如果我有時間以後,我會自己測試一下,並讓你知道。

+3

我已經構建四項測試中試圖修改子程序的參數。有外部子程序的兩個測試 - 即在一個文件中 - 有或沒有意圖(inout)。編譯器不會抱怨任何這些。這不是一個驚喜(沒有界面)和由此產生的EXE段錯誤。我已經卡住的子程序的模塊中的最後兩個測試,看看在針對無意圖殼體和一個編譯器錯誤的段錯誤(「實際參數(1)必須是可定義爲僞參數‘B’是INTENT = OUT/INOUT「)與接口。這是來自debian系統的gfortran 4.4.4-2。 – 2010-05-21 09:22:15

+0

非常好,我們都學到了一些東西。 – 2010-05-21 09:47:36

+1

這些天參數被放置在內存的只讀標記部分,但這並非總是如此。在很老的編譯器一個著名的例子是重新定義數字常量的http://coding.derkeiler.com/Archive/Fortran/comp.lang.fortran/2005-01/0485.html – 2012-02-29 08:19:56

3

要了解輸入/輸出意向的角色,你需要知道,在內部,Fortran語言有效按引用傳遞變量。這並不總是與通過引用傳遞相同。

如果將二維數組的內部子部分傳遞給子例程(即:data(i1:i2, j1:j2)),Fortran會將該數據複製到連續的內存部分,並將新地址傳遞給例程。返回時,數據被複制回原來的位置。

通過指定INTENT,編譯器可以知道跳過複製操作中的一個。

它不僅充當修改要保持不變的數據的故障保護,而且還與大型數據集處理時,可以加速你的代碼。