2013-03-27 44 views
9

使用模塊與use語句或單獨的文件與include語句之間的實際區別是什麼?我的意思是,如果我有一個在整個程序中使用很多的子程序:什麼時候或爲什麼要把它放在一個模塊中,或者寫在一個單獨的文件中,並將它包含在程序中需要的其他部分用過的?Fortran中INCLUDE和模塊之間的區別

另外,是否將所有子程序寫入單獨文件並在模塊內部使用include來編寫所有子程序?特別是如果子例程中的代碼很長,以便更好地組織代碼(這樣所有子例程都打包在mod中,但是如果我必須編輯一個子程序,我不需要走迷宮般的代碼)。

回答

16

兩個地圖之間的概念差異到非常顯着的實際差異。

INCLUDE行在源代碼級別運行 - 它實現簡單(「啞」)文本包含。如果沒有任何特殊的處理器對include文件中的「文件名」的解釋(實際上並不需要文件),那麼完整的源代碼可以非常容易地由程序員手動拼接在一起並送入編譯器,而沒有區別永遠在源的語義。包含的來源沒有單獨的真實解釋 - 其含義完全取決於引用包含來源的包含行的上下文。

模塊在程序高得多的實體級別運行,即在編譯器正在考慮源實際描述的事物的級別。一個模塊可以獨立於下游用戶進行編譯,一旦編譯完成,編譯器就可以準確知道模塊可以提供給程序的內容。

通常什麼人使用包括線是希望做的是什麼模塊實際上是設計做。

示例問題:

  • 由於實體聲明可以分佈在多個語句通過包括源描述的實體可能不是你所期望的。考慮到包括以下來源:

    INTEGER :: i

    在隔離它看起來像這樣聲明的名稱i爲一個整數標量(或者一個功能誰知道呢?!)。現在考慮下面的範圍,包括上面:

    INCLUDE "source from above"
    DIMENSION :: i(10,10)

    i現在是一個等級×2個陣列!也許你想讓它成爲一個指針?一個ALLOCATABLE?一個虛假的爭論?也許這會導致錯誤,或者它可能是有效的來源!將隱式類型輸入到混合中以真正複合潛在的樂趣。

    一個模塊中定義的實體的是「完全」由模塊限定。可以改變特定於使用範圍的屬性(VOLATILE,可訪問性等),但基本實體保持不變。名稱衝突被明確地調出,並且可以使用USE語句中的重命名子句輕鬆解決。

  • Fortran語言對語句排序的限制(規範語句必須可執行語句之前,等等)。包括的來源也受限於這些限制,在包含的範圍內,不是來源定義點的範圍內的

    充分混合與一些完全鈍角錯誤消息語句函數定義(規範的部分)和賦值語句(可執行部分)之間源歧義或更糟的是,無聲接受的錯誤代碼的編譯器。

    有在哪裏出現引用模塊USE語句的要求,但實際的模塊程序單元的源完全獨立於它的使用點的。

  • 有花式到跨相關程序共享一些全局狀態和要使用包括哪些內容?讓我向您介紹常見塊以及相關聯的序列關聯概念...

    序列關聯是早期底層Fortran處理器實現的不幸流血,這是一種容易出錯,不靈活的反優化時間錯誤。

    模塊變量使得公共塊及其相關的弊病完全不必要的。

  • 如果您使用的是包含行,請注意您並未實際包含常用過程的來源(第一段中的建議只會導致編譯器語法錯誤的消失) 。你通常會做的是包含描述該過程的接口的源代碼。對於任何非平凡的過程,描述界面的源與過程的完整源不同 - 意味着您現在需要維護同一事物的兩個源代表。這是一個容易出錯的維護負擔。

    如前所述 - 編譯器自動獲取一個模塊程序的界面的知識(編譯器的知識是「明確的」,因爲它居然看到了程序的代碼 - 因此稱爲「顯式接口」)。程序員不需要做更多的事情。

    上述結果是,除非有很好的理由相反(可能存在循環或過度依賴),否則不應使用外部子程序- 基本的出發點應該是一切在模塊或主程序中。

其他海報提及模塊的源代碼組織的好處 - 包括能夠將相關的程序和其他「東西」到一包,有超過的內部實現細節可訪問控制。

我接受有包括線按問題的第二段的有效使用 - 在大型模塊的尺寸變得笨重。 F2008通過子模塊解決了這個問題,這也帶來了其他一些好處。一旦它們得到廣泛支持,應該放棄包含線的解決方法。

第二個有效的用法是克服通用編程技術(C++提供了什麼模板)缺乏支持 - 即操作涉及的對象類型可能會有所不同,但描述什麼的令牌序列對這些對象做的事情本質上是一樣的。在語言排序之前可能還需要十年左右的時間。

+0

因此,在不同文件中分離子例程,然後在模塊中使用include,沒有缺點,對吧?我從來沒有聽說過子模塊。 – Nordico 2013-03-28 16:18:50

+1

我只會考慮如果我有非常大的源文件或作爲傳統源遷移的一部分。如果可能的話,我會首先考慮將模塊分解成多個「子」模塊,然後將這些模塊與USE語句在父模塊中彙總在一起。但是,對於複雜的類型/過程依賴關係和/或Fortran的PUBLIC/PRIVATE輔助功能的工作方式,使用子模塊可能並不總是可行。您可能會發現,將模塊的源與INCLUDE行拼接在一起會混淆一些構建系統。 – IanH 2013-03-28 19:08:01

6

將過程放入模塊並使用這些模塊使過程的接口顯式化。它允許Fortran編譯器檢查調用中的實際參數與過程的僞參數之間的一致性。這防範了各種程序員的錯誤。對於Fortran> = 90的某些「高級」功能,顯式接口也是必需的;例如,可選或關鍵字參數。沒有明確的接口,編譯器將不會生成正確的調用。僅僅包含一個文件並不能提供這些優點。

+1

我會走的更遠,我不認爲有使用包括文件的任何理由。 – 2013-03-27 17:37:01

+0

@HighPerformanceMark:窮人的泛型編程? – eriktous 2013-03-27 21:11:02

+1

就像我寫的*我不知道有什麼好的理由使用包含文件*。但是這是一個意見 – 2013-03-27 21:37:38

3

M.S.B的答案很好,可能是選擇模塊而非include的最重要原因。我想再補充一些想法。

如果這對您來說很重要,那麼使用模塊可以減少編譯後的二進制大小。一個模塊被編譯一次,當你使用代碼的時候,你會象徵性地加載該模塊。當你include一個文件,你實際上是插入新的代碼到你的例程。如果您使用include很多,它可能會導致您的二進制文件很大,同時也增加了編譯時間。

您還可以使用模塊在Fortran 90中虛擬OOP樣式編碼,方法是巧妙地使用模塊中的公共和私有函數以及用戶定義的類型。即使你不想這樣做,它也提供了一種很好的方法來將邏輯上屬於一起的功能分組。

相關問題