2016-03-04 200 views
2

我不理解的的重要性,通過定義主程序外的子程序中包含Fortran 90的包含聲明

聲明例如

PROGRAM BLABLA 

IMPLICIT NONE 

INTEGER :: i,j,k 

i = 1; j = 1;k =1 

PRINT *, i,j,k 

CALL ABC(i,j,k) 

PRINT *, i,j,k 

CONTAINS 

    SUBROUTINE ABC(r,s,t) 

    IMPLICIT NONE 

    INTEGER, INTENT(IN) :: r,s 
    INTEGER, INTENT(OUT) :: t 

    t = r + s 

    END SUBROUTINE ABC 
END PROGRAM BLABLA 

和一個。我理解函數,需要指定函數的類型,但對於子例程,它不是必需的。我有興趣瞭解這樣做是否有任何額外的注意事項?

PROGRAM BLABLA 

IMPLICIT NONE 

INTEGER :: i,j,k 

i = 1; j = 1;k =1 

PRINT *, i,j,k 

CALL ABC(i,j,k) 

PRINT *, i,j,k 

END PROGRAM BLABLA 

SUBROUTINE ABC(r,s,t) 

IMPLICIT NONE 

INTEGER, INTENT(IN) :: r,s 
INTEGER, INTENT(OUT) :: t 

t = r + s 

END SUBROUTINE ABC 

回答

3

在這兩個您的第一和第二版本嘗試改變線

CALL ABC(i,j,k) 

CALL ABC(i,j) 

看看會發生什麼,首先在編譯的時候,其次在運行時。

當你這樣做了,並報告了你的發現後,我可以把它變成一個正確的答案。

OK,所以這裏的答案,其中大部分你已經想通了:

在過去,Fortran 90的前,是常見的FORTRAN(每個人都喊在那些日子裏的名字)程序編入單獨的「單位」(現在仍然是)。在你的第二個版本中,程序和子程序是分開的單元並單獨編譯。編譯器沒有可用的信息來檢查對子例程的調用是否與子例程簽名匹配 - 這是留給程序員檢查的。不正確地調用子程序,幾乎任何事情都可能發生 - 如果你幸運的話,程序崩潰或產生明顯錯誤的結果,如果你不幸,它會產生不明顯錯誤但仍然錯誤的結果。

如果在程序單元的作用域中包含子程序的源代碼,並使用contains部分(如在程序的第一個版本中那樣),編譯器將爲該子程序創建一個接口,並可以檢查任何對子程序的調用在形式上是正確的。因此沒有編譯你發現。

另一種讓編譯器爲子程序生成接口的方法,這些方法也可以用於函數,也就是將它們放入模塊中,並將其放入程序中的模塊中。你會發現很多例子來說明如何在其他Q和As上實現。

將子程序放入模塊中並不完全等同於將其包含在contains部分中。在contains節中,子程序可以使用程序中聲明的變量,而不通過子程序的參數列表。這是一個糟糕的編程習慣,但你確實遇到過它。

+0

當我沒有** CONTAINS **時,它編譯,但然後給我一個錯誤的答案(任意大)。當我有** CONTAINS **時,它不允許我編譯。所以我猜** CONTAINS **作爲參數的附加檢查。到目前爲止,我正在編寫沒有** CONTAINS **的代碼。如果相同的代碼用** CONTAINS **編譯**,我可以確信,其他代碼在參數上是正確的。更確切地說,如果在任何代碼中都沒有傳遞參數(但在MODULES中保存爲全局變量),兩者是否都相同? – Vaidyanathan