INCLUDE和Fortran模块之间的区别 [英] Difference between INCLUDE and modules in Fortran

查看:267
本文介绍了INCLUDE和Fortran模块之间的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

解决方案

两个地图的概念差异通过非常显着的实际差异。

INCLUDE行在源代码级别运行 - 它实现简单(哑)文本包含。如果没有任何特殊的处理器对include文件中的文件名的解释(实际上并不需要文件),那么完整的源代码可以很容易地由程序员手动拼接在一起并送入编译器,没有什么区别永远在源的语义。包含的源代码没有真正的解释 - 它的含义完全取决于引用包含源代码的包含行的上下文。

模块的运行速度要高得多程序的实体级别,即在编译器正在考虑源实际描述的事物的级别。一个模块可以独立于其下游用户进行编译,一旦编译完成,编译器就可以准确知道模块可以提供给程序的内容。



包含的行是 hoping 要做的是实际设计的模块。



示例问题:

>


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

    INTEGER :: i



    隔离它看起来像这样声明名称 i 为一个整数标量(或者可能是一个函数?谁知道!)。现在考虑下面的范围,包括上面的内容:



    INCLUDE源自上面

    DIMENSION :: i(10,10)



    i 现在是一个排名第二的数组!也许你想让它成为一个指针?一个ALLOCATABLE?一个虚假的争论?也许这会导致错误,或者它可能是有效的来源!将隐式类型输入到混合中以真正复合潜在的乐趣。

    模块中定义的实体完全由模块定义。可以改变特定于使用范围的属性(VOLATILE,可访问性等),但基本实体保持不变。名字冲突被明确地调出,并且可以用USE语句中的重命名子句轻松解决。

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

    对于一些完全钝的错误消息,或者更糟的是,编译器无声地接受,在语句函数定义(规范部分)和赋值语句(可执行部分)的错误代码。

    对引用模块的USE语句的出现位置有要求,但实际模块程序单元的来源完全独立于其使用点。

  • Fancy拥有一些全局状态可以在相关过程中共享,并且您想使用include?让我向您介绍常见块以及序列关联的相关底层概念......序列关联是早期底层Fortran处理器实现的不幸流血,它是一种

    模块变量使普通模块及其相关的恶魔完全不必要。


  • <如果您使用的是包含行,请注意您实际上并没有包含常用过程的源代码(第一段中的建议只会导致编译器中的语法错误) 。你通常会做的是包含描述过程的接口的源代码。对于任何非平凡的过程,描述界面的源与过程的完整源不同 - 意味着您现在需要维护同一事物的两个源代表。这是一个容易出错的维护负担。

    如前所述,编译器会自动获得模块过程接口的知识(编译器知识是明确的程序的代码 - 因此是术语显式接口)。没有必要让程序员做更多的事情。



    以上的结果是,外部子程序不应该在所有中使用,除非存在非常好的理由相反(也许存在循环或过度依赖) - 基本的出发点应该是将所有东西放在模块或主程序中。

    $其他海报已经提到了模块的源代码组织优势 - 包括将相关过程和其他东西分组到一个包中的能力,内部实现细节的可访问性。



    我接受根据问题的第二段有效使用INCLUDE行 - 大型模块的大小变得笨重。 F2008用子模块解决了这个问题,这也带来了其他一些好处。一旦它们得到广泛的支持,应该放弃包含线的解决方法。

    第二个有效的用法是克服泛型编程技术缺乏语言支持模板以C ++提供) - 即操作涉及的对象类型可能会有所不同,但描述对这些对象做什么的令牌序列本质上是相同的。这可能还需要十年左右的时间才能完成。


    What are the practical differences between using modules with the use statement or isolated files with the include statement? I mean, if I have a subroutine that is used a lot throughout a program: when or why should I put it inside a module or just write it in a separate file and include it in every other part of the program where it needs to be used?

    Also, would it be good practice to write all subroutines intended to go in a module in separate files and use include inside the module? Specially if the code in the subroutines is long, so as to keep the code better organized (that way all subroutines are packed in the mod, but if I have to edit one I don't need to go though a maze of code).

    解决方案

    The conceptual differences between the two map through to very significant practical differences.

    An INCLUDE line operates at the source level - it accomplishes simple ("dumb") text inclusion. In the absence of any special processor interpretation of the "filename" (no requirement for that actually to be a file) in the include line the complete source could quite easily be manually spliced together by the programmer and fed to the compiler with no difference what-so-ever in the semantics of the source. Included source has no real interpretation in isolation - its meaning is completely dependent on the context in which the include line that references the included source appears.

    Modules operate at the much higher entity level of the program, i.e. at the level where the compiler is considering the things that the source actually describes. A module can be compiled in isolation of its downstream users and once it has been compiled the compiler knows exactly what things the module can provide to the program.

    Typically what someone using include lines is hoping to do is what modules were actually designed to do.

    Example issues:

    • Because entity declarations can be spread over multiple statements the entities described by included source might not be what you expect. Consider the following source to be included:

      INTEGER :: i

      In isolation it looks like this declares the name i as an integer scalar (or perhaps a function? Who knows!). Now consider the following scope that includes the above:

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

      i is now a rank two array! Perhaps you want to make it a POINTER? An ALLOCATABLE? A dummy argument? Perhaps that results in an error, or perhaps it is valid source! Throw implicit typing into the mix to really compound the potential fun.

      An entity defined in a module is "completely" defined by the module. Attributes that are specific to the scope of use can be changed (VOLATILE, accessibility, etc), but the fundamental entity remains the same. Name clashes are explicitly called out and can be easily worked around with a rename clause on the USE statement.

    • Fortran has restrictions on statement ordering (specification statements must go before executable statements, etc.). Included source is also subject to those restrictions, again in the context of the point of inclusion, not the point of source definition.

      Mix well with source ambiguity between statement function definitions (specification part) and assignment statements (executable part) for some completely obtuse error messages or, worse, silent acceptance by the compiler of erroneous code.

      There are requirements on where the USE statement that references a module appears, but the source for the actual module program unit is completely independent of its point of use.

    • Fancy having some global state to be shared across related procedures and you want to use include? Let me introduce you to common blocks and the associated underlying concept of sequence association...

      Sequence association is a unfortunate bleed-through of early underlying Fortran processor implementation that is an error prone, inflexible, anti-optimisation anachronism.

      Module variables make common blocks and their associated evils completely unnecessary.

    • If you were using include lines, then note that you don't actually include the source of a commonly used procedure (the suggestion in your first paragraph is just going to result in a morass of syntax errors from the compiler). What you would typically do is include source that describes the interface of the procedure. For any non-trivial procedure the source that describes the interface is different from the complete source of the procedure - implying that you now need to maintain two source representations of the same thing. This is an error prone maintenance burden.

      As mentioned - the compilers automatically gains knowledge of the interface of a module procedure (the compiler knowledge is "explicit" because it actually saw the procedure's code - hence the term "explicit interface"). No need for the programmer to do anything more.

      A consequence of the above is that external subprograms should not be used at all unless there are very good reasons to the contrary (perhaps the existence of circular or excessively extensive dependencies) - the basic starting point should be to put everything in a module or main program.

    Other posters have mentioned the source code organisation benefits of modules - including the ability to group related procedures and other "stuff" into the one package, with control over accessibility of internal implementation details.

    I accept there is a valid use of INCLUDE lines as per the second paragraph of the question - where large modules become unwieldy in size. F2008 has addressed this with submodules, which also bring a number of other benefits. Once they become widely supported the include line work-around should be abandoned.

    A second valid use is to overcome a lack of support by the language for generic programming techniques (what templates provide in C++) - i.e. where the types of objects involved in an operation may vary, but the token sequence that describes what to do on those objects is essentially the same. It might be another decade or so before the language sorts that out.

    这篇关于INCLUDE和Fortran模块之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆