3

サブルーチンがあるとします:

subroutine foo(x, Nx)
    implicit none
    integer, intent(IN) :: x
    integer, intent(IN) :: Nx

    select case(x)
        case (1)
            write(*,*) "Minimum value"
        case (Nx)
            write(*,*) "Maximum value"
        case default
            write(*,*) "Somewhere in-between"
    end select
end subroutine foo

ドライバーが次のようになっているとします。

program main
    implicit none

    interface
        subroutine foo(x,Nx)
            integer, intent(IN)  :: x
            integer, intent(IN)  :: Nx
        end subroutine foo
    end interface

    integer, parameter :: Nx = 100
    integer :: x

    call foo(20, Nx)

end program main

上記のプログラムは、サブルーチンでcase (Nx)無効なため、コンパイルされません。具体的には、ifort 16 で次のエラーが発生します。

エラー #6601: CASE ステートメントでは、case-value は定数式でなければなりません。

言い換えると、 Nx はを介し​​て実質的にサブルーチン定数として宣言されintent(IN)ますが、リテラル定数またはparameter型のいずれかである必要がありますinteger

Nxcase ステートメントを、既知の定数パラメーターとして受け入れるようにする方法はありますか? Nx渡されたことを宣言する方法はありparameterますか?

この単純で短い例では、if-then-elseif-else-end ブロックで十分であることはわかっていますが、そうすると、この質問に対する答えがわかりません。:-)

4

2 に答える 2

5

if ステートメントを使用するだけです。サブルーチン引数 (これをパラメーターと呼びます) は、確かにパラメーター (名前付き定数) ではありません。はintent(in)それを効果的にパラメーターにするわけではありません。変更しないという約束にすぎませんが、それを回避する方法があります。case ステートメントには、コンパイル時の定数が必要です。

于 2015-09-13T19:40:36.310 に答える
3

「 Nxを、既知の定数パラメーターとして受け入れる」方法があるかどうかを尋ねます。Nxが定数式を形成することはわかりませんが、そうでないことは確かにわかってます。

Nxを定数式にする唯一の方法はNx、名前付き定数にすることです。名前付き定数であることは、仮引数であることと互換性がありません。仮引数であっても、属性のintent(in)有無にかかわらず、名前付き定数に関連付けられています。intent

概念的にはfoo、メイン プログラムに関する限り、サブルーチンは外部プロシージャです (インターフェイス ブロックがあります)。これは、スタンドアロンのものとしてコンパイルされ、後の段階でリンクされることを期待することを意味します。最終的な用途に関係なく、有効でなければなりません。[とは言っても、外部手続きではない場合でも、言語仕様に関する限り、最初の部分は依然として有効です。]

Nx当然、構造体を使用してこれを書き換えたくない場合は、サブルーチンに名前付き定数を含める方法が他にもありますif

于 2015-09-13T19:41:04.610 に答える