Fortran中的INTERFACE块和MODULE过程之间的区别是什么? [英] Which is the diffeence between an INTERFACE block and a MODULE procedure in fortran?

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

问题描述

我对模块内部的接口块的使用以及使用CONTAINS语句为模块内部的过程创建显式接口感到困惑。



我通常使用模块内的接口块编写过程。例如,

  MODULE ModExample 
INTERFACE
SUBROUTINE Sumatory(a,b,c)
IMPLICIT NONE

INTEGER,INTENT(IN):: a
INTEGER,INTENT(OUT):: b
INTEGER,INTENT(OUT):: c
END SUBROUTINE Sumatory
END INTERFACE
END MODULE ModExample

SUBROUTINE Sumatory(a,b,c)
IMPLICIT NONE

INTEGER,INTENT (IN):: a
INTEGER,INTENT(OUT):: b
INTEGER,INTENT(OUT):: c

!可执行语句

END SUBROUTINE Sumatory

这对我很有用。但是它也可以使用模块内部的CONTAINS stament编写,实际上这就是示例程序在我参考的Fortran书籍中编写的方式。

 

$ b $ SUB







$ $ b INTEGER,INTENT(IN):: a
INTEGER,INTENT(OUT):: b
INTEGER,INTENT(OUT):: c

!可执行语句here

END SUBROUTINE Sumatory
END MODOULE ModExample

所以什么是错的与INTERFCE块?都是等同的结构?我应该使用哪两种方法?也许所有这些问题都可以用一个很大的取决于来回答,但我希望你给出一个关于它们之间差异的解释。这取决于,但除非你有相反的理由,否则使用模块过程(之后的)。包含)。



第一种方法错误的是,您必须指定过程的接口两次 - 一次在接口块中,一次在程序定义本身。在第二种情况下,界面只在程序定义中指定一次。需要维护多个规范是潜在的错误来源。

详述:

在第一个代码示例,后面的SUBROUTINE和END SUBROUTINE语句之间的源(不在接口块内)就是所谓的外部子程序。这是一个单独的计划单位。外部子程序定义了一个外部过程



在第二个代码示例中,SUBROUTINE和END SUBROUTINE语句之间的源模块中的CONTAINS语句是模块子程序。它是模块程序单元的一部分。该模块子程序定义了一个模块过程

(一个子程序指的是源代码结构,而一个过程指的是)

还有一些内部子程序(它们出现在主机外部或模块子程序或主程序中的CONTAINS语句之后),它们定义了内部程序,和单独的模块子程序,这是定义模块过程的另一种方式。

Fortran程序单元(主程序,模块,子模块,外部子程序,块数据)使用模型单独编译。编译一个特定的程序单元时,编译器的行为就好像它忽略了程序中的任何其他程序单元,禁止在源代码中明确指定相关规范。



一个如果你在一个范围内引用一个外部过程而没有明确地告诉编译器这个外部过程是什么样的,那么编译器必须从引用的方式隐含地推断外部过程的接口(过程有一个隐式接口)。以这种方式引用的过程不能使用该语言的许多新的参数传递功能(因为编译器不知道如何正确调用和传递参数)。实际上,编译器也不太可能识别诸如不匹配的参数类型之类的错误。

接口块,比如第一个代码示例中的接口块,可以用来明确地指定外部程序的接口。对可以访问显式接口的源代码中的外部过程的引用可以使用所有现代参数传递功能,并且可能会获得更好的编译器错误检测。然而,程序员仍然有责任确保接口体的相关特性和实际的外部过程定义是一致的。

该语言还有一个要求,即只有一个过程的界面可以在范围单元中访问。在定义它的外部子程序内部,过程的接口已经是显式的,所以程序员有责任确保外部过程内不能访问同一外部过程的接口体。



允许在程序单元之间共享信息的显式规范之一是USE语句,它使USE语句出现的范围中可用模块定义的事物的知识成为可能。这包括有关由模块定义或声明的过程的知识。

(该语言要求在模块使用之前,模块公共部分的源可用,这实际上意味着模块的源必须具有)在编译USE语句之前编译模块。)



与外部过程不同,模块过程或内部过程的接口始终显式位于其标识符是可访问的 - 没有必要为模块过程或内部(除了独立的模块子程序,你不能有接口体)有一个接口体。



总结:

第一个例子 - 你有一个模块带有一个外部过程的接口体,然后是外部过程本身。您可以引用该外部过程而无需使用该模块,在这种情况下会使用隐式接口(受限功能,容易出错)。或者,如果该模块在引用范围内被USE使用,则该接口将是明确的。在这种情况下,程序员必须确保接口主体和外部过程定义匹配,并且外部过程的接口主体在外部过程中不可访问。这是容易出错和维护的麻烦。

第二个例子 - 你有一个模块,它有一个模块过程。如果不使用相关模块,则不能通过其名称引用模块过程。这种引用的界面将始终是明确的。没有必要为该过程维护一个单独的接口体。



第一种形式超过第二种形式的唯一好理由是如果您需要中断一个编译依赖性循环或以其他方式限制长编译依赖链。


I'm a bit confused about the use of an interface block inside a module and the use of the CONTAINS statement to create an "explicit interface" for a procedure inside a module.

I usually write a procedure using an interface block inside a module. For example,

    MODULE ModExample
    INTERFACE 
        SUBROUTINE Sumatory(a, b, c)
            IMPLICIT NONE

            INTEGER, INTENT(IN)::a
            INTEGER, INTENT(OUT)::b
            INTEGER, INTENT(OUT)::c
        END SUBROUTINE Sumatory
    END INTERFACE
    END MODULE ModExample

   SUBROUTINE Sumatory(a, b, c)
      IMPLICIT NONE

      INTEGER, INTENT(IN)::a
      INTEGER, INTENT(OUT)::b
      INTEGER, INTENT(OUT)::c

      !Executable statements here

   END SUBROUTINE Sumatory

And this works for me. But it can also be written using the CONTAINS stament inside the module, and actually this is the way in which example procedures are written in the Fortran books that I've consulted.

MODULE ModExample

CONTAINS

SUBROUTINE Sumatory(a, b, c)
    IMPLICIT NONE

    INTEGER, INTENT(IN)::a
    INTEGER, INTENT(OUT)::b
    INTEGER, INTENT(OUT)::c

    !Executable statements here

END SUBROUTINE Sumatory
END MODOULE ModExample

So what is wrong with the INTERFCE block? Are both equivalent constructs? Which of the two aproaches should I use? Maybe all this questions can be answered with a big "it depends" but I would like you to give an explanation about their differences. Thanks in advance.

解决方案

It depends, but unless you have a good reason to the contrary, use module procedures ("after the contains").

The thing that is "wrong" with the first approach is that you have had to specify the interface of the procedure twice - once in the interface block and once in the procedure definition itself. In the second case the interface is only specified once - in the procedure definition. The need to maintain multiple specifications is a potential source of error.

Elaborating:

In the first code example, the source between the latter SUBROUTINE and END SUBROUTINE statements (not inside the interface block) is what's known as an external subprogram. This is a program unit in its own right. The external subprogram defines an external procedure.

In the second code example, the source between the SUBROUTINE and END SUBROUTINE statements, that appears after the CONTAINS statement in the module, is a module subprogram. It is part of the module program unit. That module subprogram defines a module procedure.

(A "subprogram" refers to the source code construct, while a procedure refers to the thing that the source code defines.)

There also exist internal subprograms (they appear after the CONTAINS statement inside a host external or module subprogram, or main program) which define internal procedures, and separate module subprograms, which are another way of defining module procedures.

Fortran program units (main programs, modules, submodules, external subprograms, block data) use a model of separate compilation. When compiling a particular program unit, the compiler acts as if it is oblivious to any other program unit in the program, bar explicit specifications in the source to the contrary.

One consequence of this is that if you reference an external procedure in a scope without explicitly telling the compiler what that external procedure looks like, then the compiler must implicitly deduce the interface for the external procedure from the manner of the reference (the procedure has an implicit interface). Procedures referenced in such a manner cannot use many of the newer argument passing features of the language (because the compiler doesn't know how to invoke and pass arguments to the procedure correctly). Practically compilers are also much less likely to identify errors such as mismatched argument types.

An interface block, such as the one in the first code example, can be used to explicitly specify the interface of an external procedure. References to the external procedure in source code where that explicit interface is accessible can use all the modern argument passing features and are likely to get much better compiler error detection. However, it is still incumbent on the programmer to make sure that the relevant characteristics of the interface body and actual external procedure definition are consistent.

The language also has a requirement that only one interface for a procedure be accessible in a scoping unit. Inside the external subprogram that defines it the interface for the procedure is already explicit, so it is incumbent on the programmer to make sure that an interface body for the same external procedure is not accessible inside the external procedure.

One of the explicit specifications that allows information to be shared between program units is a USE statement, which makes knowledge about the things defined by a module available in the scope where the USE statement appears. This includes knowledge about the procedures defined or declared by the module.

(The language requires that the source for the public portions of a module "be available" before the module is used, which practically means that the source for the module must have been compiled before a USE statement for the module is compiled.)

Unlike external procedures, the interface for a module procedure or internal procedure is always explicit in a scope where its identifier is accessible - there is no need to have a interface body for the module procedure or internal (separate module subprograms aside, you must not have an interface body).

In summary:

First example - you have a module with an interface body for an external procedure, and then the external procedure itself. You can reference that external procedure without needing to USE the module, in which case an implicit interface is used (limited features, error prone). Alternatively if the module is USE'd in the referencing scope the interface will be explicit. In that case the programmer must ensure that the interface body and external procedure definition match and that the interface body for the external procedure is not accessible inside the external procedure. This is error prone and a maintenance nuisance.

Second example - you have a module that has a module procedure. You cannot reference the module procedure through its name without USE'ing the relevant module. The interface for such a reference will always be explicit. There is no need to maintain a separate interface body for the procedure.

The only good reason to us the first form over the second form is if you need to break a compilation dependency loop or otherwise limit a long compilation dependency chain.

这篇关于Fortran中的INTERFACE块和MODULE过程之间的区别是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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