Fortran中INCLUDE和modules的区别

Fortran中INCLUDE和modules的区别,module,include,fortran,Module,Include,Fortran,使用带有use语句的模块或带有include语句的独立文件之间的实际区别是什么?我的意思是,如果我有一个在整个程序中经常使用的子程序:什么时候或者为什么我应该把它放在一个模块中,或者只是把它写在一个单独的文件中,并把它包含在程序的其他需要使用的部分 此外,将模块中的所有子例程写入单独的文件中,并在模块内部使用include,这是否是一种良好的做法?特别是如果子例程中的代码很长,以便更好地组织代码(这样所有子例程都打包在mod中,但是如果我必须编辑一个,我就不需要经历代码的迷宫)。将过程放入模块并

使用带有
use
语句的模块或带有
include
语句的独立文件之间的实际区别是什么?我的意思是,如果我有一个在整个程序中经常使用的子程序:什么时候或者为什么我应该把它放在一个模块中,或者只是把它写在一个单独的文件中,并把它包含在程序的其他需要使用的部分


此外,将模块中的所有子例程写入单独的文件中,并在模块内部使用
include
,这是否是一种良好的做法?特别是如果子例程中的代码很长,以便更好地组织代码(这样所有子例程都打包在mod中,但是如果我必须编辑一个,我就不需要经历代码的迷宫)。

将过程放入模块并使用这些模块可以使过程的接口显式化。它允许Fortran编译器检查调用中的实际参数与过程的伪参数之间的一致性。这可以防止程序员犯各种错误。Fortran>=90的某些“高级”功能也需要显式接口;例如,可选参数或关键字参数。如果没有显式接口,编译器将无法生成正确的调用。仅仅包含一个文件并不能提供这些优势。

M.S.B.的答案很好,这可能是首选模块而非包含的最重要原因。我想补充一些想法

使用模块可以减少编译后的二进制大小,如果这对您很重要的话。模块编译一次,当您
使用它时,您象征性地加载该模块以使用代码。当您
包含文件时,实际上是在将新代码插入例程中。如果大量使用
include
,可能会导致二进制文件变大,并增加编译时间


通过巧妙地使用模块中的公共和私有函数以及用户定义的类型,您还可以使用模块在Fortran 90中伪造OOP风格的编码。即使您不想这样做,它也提供了一种很好的方法来对逻辑上属于一起的函数进行分组

这两个概念上的差异映射到了非常显著的实际差异

INCLUDE行在源代码级别运行-它完成简单(“哑”)文本包含。在include行中没有对“filename”(不要求该文件实际上是一个文件)的任何特殊处理器解释的情况下,完整的源代码可以很容易地由程序员手动拼接在一起,并提供给编译器,而与源代码的语义没有任何区别。包含的源代码没有孤立的真正解释-其含义完全取决于引用包含的源代码的包含行出现的上下文

模块在程序更高的实体级别上运行,即编译器考虑源代码实际描述的内容的级别。模块可以独立于其下游用户进行编译,一旦编译完成,编译器就确切地知道模块可以向程序提供什么

通常,使用include行的人希望做的是模块实际设计的目的

示例问题:

  • 因为实体声明可以分布在多个语句中,所以包含的源描述的实体可能不是您所期望的。考虑以下来源:

    INTEGER::i

    单独来看,它似乎将名称
    i
    声明为整数标量(或者可能是一个函数?谁知道呢!)。现在考虑下面的范围,包括上面的内容:

    包括“来自上方的来源”

    维度::i(10,10)

    i
    现在是一个二级数组!也许你想让它成为一个指针?可分配的?伪论点?这可能会导致错误,也可能是有效的源代码!将隐式键入加入到组合中,以真正增加潜在的乐趣

    模块中定义的实体由模块“完全”定义。特定于使用范围的属性可以更改(易失性、可访问性等),但基本实体保持不变。名称冲突是显式调用的,可以通过USE语句中的rename子句轻松解决

  • Fortran对语句顺序有限制(规范语句必须在可执行语句之前,等等)。包含的源也受到这些限制,同样是在包含点的上下文中,而不是在源点定义的上下文中

    对于一些完全迟钝的错误消息,或者更糟糕的是,编译器无声地接受错误代码,可以很好地处理语句函数定义(规范部分)和赋值语句(可执行部分)之间的源代码歧义

    引用模块的USE语句出现在何处是有要求的,但实际模块程序单元的源完全独立于其使用点

  • 是否希望在相关过程中共享一些全局状态,并希望使用include?让我向您介绍常见块和序列关联的相关基本概念

    序列关联是早期底层Fortran处理器实现的一个不幸的漏洞,它是一个容易出错、不灵活、反优化的时代错误

    模块变量使得公共块及其相关的邪恶完全不必要

  • 如果您使用的是include行,那么请注意,您实际上没有包含常用过程的源代码(第一段中的建议只会导致编译器出现大量语法错误)。您通常会做的是包含sou