派生型

派生型として認識される追加のデータ型は、 組み込みデータ型や他の派生型から作成することができます。 派生型の名前 (type_name)、データ型、 および派生型のコンポーネントの名前を定義するには、型定義が必要です。

+----------------------------------IBM 拡張----------------------------------+

レコード構造は、集合非配列データの操作で一般的に使用される拡張機能です。 Fortran 90 では、レコード構造は派生型よりも前に導入されました。

レコード構造で使用される構文は、多くの場合 Fortran 派生型で 使用される構文に似ています。 また、多くの場合、これらの 2 つの機能のセマンティクスも類似しています。 このため、XL Fortran では、これらの 2 つの機能をほぼ完全に交換できるような方法で レコード構造がサポートされています。 そのため、以下のようになります。

ただし、以下の違いがあります。

+------------------------------End of IBM 拡張-------------------------------+



>>-DERIVED_TYPE_statement--------------------------------------><
 
 
>>-+------------------------+----------------------------------><
   '-PRIVATE_SEQUENCE_block-'
 
 
>>-component_def_stmt_block------------------------------------><
 
 
>>-END_TYPE_statement------------------------------------------><
 
 

DERIVED_TYPE_statement
構文の詳細については、派生型を参照してください。

PRIVATE_SEQUENCE_block
PRIVATE ステートメント (キーワードのみ)、 SEQUENCE ステートメントのいずれかまたはその両方を含みます。 それぞれのステートメントの 1 つだけを指定できます。 構文の詳細については、PRIVATEおよび SEQUENCEを 参照してください。

component_def_stmt_block
1 つ以上の型宣言ステートメントから構成され、派生型のコンポーネントを定義します。 型宣言ステートメントには、DIMENSIONFORTRAN 2003 の開始ALLOCATABLEPRIVATEPUBLIC FORTRAN 2003 の終了、および POINTER 属性のみを指定できます。詳細な構文および説明に関しては、 型宣言を参照してください。

+---------------------------------Fortran 95---------------------------------+

さらに、Fortran 95 では、派生型の定義の 各コンポーネントに対して、デフォルトの初期化を指定することができます。 詳細な構文および説明に関しては、 型宣言を参照してください。

+-----------------------------End of Fortran 95------------------------------+

END_TYPE_statement
END TYPEを参照してください。

+---------------------------------Fortran 95---------------------------------+

Fortran 95 では派生型の直接コンポーネントには、次のものがあります。

+-----------------------------End of Fortran 95------------------------------+

各派生型は、組み込みデータ型の最終コンポーネントとして解決されるか、あるいは割り当て可能またはポインターになります。

この型名は、ローカル・エンティティーです。 これは、どの組み込みデータ型とも同じ名前にすることはできません。 ただし、BYTE および DOUBLE COMPLEX は例外です。

END TYPE ステートメントには、TYPE ステートメントで 指定したものと同じ type_name をオプションで指定することができます。

派生型のコンポーネントでは、どの組み込みデータ型でも 指定することができます。 また、コンポーネントは、事前に定義された派生型の 1 つであってもかまいません。 ポインター・コンポーネントは、そのコンポーネントの同じ派生データ型であっても かまいません。 コンポーネントの名前は、派生型内では固有でなければなりませんが、 派生型定義の有効範囲外の名前と異なっていてもかまいません。 CHARACTER 型として宣言されたコンポーネントは、 定数宣言式である長さ指定を含んでいる必要があります。アスタリスクは、 長さ指定子として使用できません。 ポインター以外の配列コンポーネントは、定数次元宣言子で宣言しなければなりません。 ポインター配列コンポーネントは、deferred_shape_spec_list で 宣言しなければなりません。

+-------------------------Fortran 2003 ドラフト標準--------------------------+

派生型が BIND 属性を持つ場合、この派生型には一定の型を持つコンポーネントしか指定できません。コンポーネントは相互運用可能型でなければなりません。(詳細については、型の相互運用可能性を参照してください。)

BIND 派生型を扱う際には、以下の規則に注意してください。

+----------------------End of Fortran 2003 ドラフト標準----------------------+

デフォルトでは、記憶順序は、コンポーネントの定義順序に暗黙指定されません。 ただし、SEQUENCE ステートメントを指定すると、 派生型は、順序派生型 になります。 順序派生型では、コンポーネントの順序に従って、 この派生型として宣言されたオブジェクトの記憶順序が指定されます。 順序派生型のコンポーネントが派生型の場合、 その派生型も順序派生型でなければなりません。

順序派生型を使用すると、データの並びが揃わなくなることがあります。 これは、プログラムのパフォーマンスに悪影響を与えます。

+-------------------------Fortran 2003 ドラフト標準--------------------------+

派生型に BIND 属性がある場合、以下のようになります。

+----------------------End of Fortran 2003 ドラフト標準----------------------+

PRIVATE ステートメントは、派生型がモジュールの 指定部分内で定義された場合にのみ、指定することができます。 派生型のコンポーネントがプライベートと宣言される型の場合、 派生型の定義で PRIVATE ステートメントを指定するか、 または派生型自体がプライベートでなければなりません。

型定義がプライベートである場合、次のものは、 定義するモジュール内でのみアクセス可能となります。

派生型の定義に、PRIVATE ステートメントが 含まれている場合、その派生型が public であっても、 そのコンポーネントは、定義するモジュール内でのみアクセスできます。 構造体コンポーネントは、定義するモジュール内でのみ使用できます。

派生型のコンポーネントのデフォルト・アクセス可能度は、PRIVATE ステートメントが指定されない限り PUBLIC となります。コンポーネントに指定された属性は、デフォルト・アクセス可能度を指定変更します。

+-------------------------Fortran 2003 ドラフト標準--------------------------+

コンポーネントが PRIVATE の場合、そのコンポーネント名には派生型定義を含むモジュールでしかアクセスできません。

PRIVATE または PUBLIC 属性を持つコンポーネントは、型定義がモジュールの指定部分内にある場合にのみ許可されます。

PRIVATE または PUBLIC 属性は、指定された宣言ステートメント内に一度しか指定できません。

PRIVATE または PUBLIC 属性は、レコード構造体の派生型コンポーネントでは指定できません。

+----------------------End of Fortran 2003 ドラフト標準----------------------+

派生型エンティティーのコンポーネントは、オブジェクトのいずれかの 最終コンポーネントが入出力ステートメントの有効範囲の単位でアクセスできない場合、入出力リスト項目として指定することはできません。 派生型オブジェクトは、ポインターまたは割り当て可能であるコンポーネントを持っている場合、 データ転送ステートメント内に指定することはできません。

派生型のスカラー・エンティティーは、 構造体 と呼ばれます。 順序派生型のスカラー・エンティティーは、 順序構造体 と呼ばれます。 構造体の型指定子は、TYPE キーワードを含み、 その後に括弧で囲まれた派生型の名前が続きます。 指定した派生型のエンティティー宣言に関する詳細は、 TYPEを参照してください。 構造体のコンポーネントは、構造体コンポーネント と呼ばれます。 構造体コンポーネント は、構造体の 1 つのコンポーネントであるか、 派生型の配列を成しているコンポーネントです。

PRIVATE 派生型のオブジェクトは、定義するモジュールの外部で使用することはできません。

デフォルトの初期化は、等号の後ろに初期化式を付けるか、 またはスラッシュで囲まれた initial_value_list を使用して指定できます。 現在、この形式の初期化は、レコード構造体宣言または 標準の派生型宣言を使用して宣言されたコンポーネントで使用されています。

+---------------------------------Fortran 95---------------------------------+

Fortran 95 で、デフォルトの初期化の候補となるデータ・オブジェクトは、 以下のような名前付きデータ・オブジェクトです。

  1. その直接コンポーネントのいずれにもデフォルトの初期化が 指定されている派生型のデータ・オブジェクト
  2. POINTER 属性と FORTRAN 2003 の開始 ALLOCATABLE FORTRAN 2003 の終了 属性のどちらもないデータ・オブジェクト
  3. 使用関連付けまたはホスト関連付けでないデータ・オブジェクト
  4. ポイント先でないデータ・オブジェクト

非ポインターかつ割り振り不可能なコンポーネントのデフォルトの初期化は、 その型の直接コンポーネントに対して行われるどのデフォルト初期化よりも優先します。

仮引き数に INTENT(OUT) が指定されているものが、 デフォルトの初期化がされている派生型である場合、 それを想定サイズ配列にすることはできません。 非ポインター・オブジェクトまたはサブオブジェクトが型定義内でデフォルトの初期化を指定されている場合、 それを DATA ステートメントによって初期化することはできません。

+-----------------------------End of Fortran 95------------------------------+

+----------------------------------IBM 拡張----------------------------------+

デフォルトの初期化付きの派生型のデータ・オブジェクトは、IBM 拡張として 共通ブロックの中に指定できます。 また、XL Fortran ではデフォルトの 初期化は、-qsave=defaultinit が 指定されていない限り、SAVE 属性を暗黙指定しません。

+------------------------------End of IBM 拡張-------------------------------+

+---------------------------------Fortran 95---------------------------------+

明示的な初期化とは異なり、コンポーネントのデフォルトの初期化を有効にするために、 データ・オブジェクトに SAVE 属性を指定する必要はありません。 デフォルトの初期化は、派生型のいくつかのコンポーネントに対して指定することができますが、すべての コンポーネントに指定する必要はありません。

ストレージに関連した記憶装置の デフォルトの初期化を指定することができます。 ただし、デフォルトの初期化を提供する デフォルトのオブジェクトまたはサブオブジェクトは、 同じ型でなければなりません。 そのオブジェクトまたはサブオブジェクトは、同じ型付きパラメーターを持たなければならず、記憶装置に同じ値を 提供しなければなりません。

直接コンポーネントは、型定義内で対応するコンポーネント定義に対して デフォルトの初期化を指定していれば、 コンポーネントへのアクセス可能性に関係なく、初期値を受け取ることになります。

デフォルトの初期化の対象になるデータ・オブジェクトの場合、 その非ポインター・コンポーネントは、最初に定義されているか、 または対応するデフォルトの初期化式によって定義されます。 そのポインター・コンポーネントは、最初に関連解除されているか、 または以下の条件のいずれかが満たされる場合は、関連解除されます。

コンポーネントに対するデフォルトの初期化を指定した派生型の オブジェクトの割り振りによって、コンポーネントは以下のようになります。

ENTRY ステートメントを持つサブプログラムでは、 デフォルトの初期化は、参照されるプロシージャー名の引き数リストに 表示される仮引き数の場合だけ実行されます。 この種の仮引き数に OPTIONAL 属性がある場合、 デフォルトの初期化はこの仮引き数がある場合に限り実行されます。

デフォルトの初期化が指定された派生型の モジュール・データ・オブジェクトが、デフォルト初期化の 候補のデータ・オブジェクトである場合には、 SAVE 属性がなければなりません。

+-----------------------------End of Fortran 95------------------------------+

標準の派生型宣言を使用して宣言された順次派生型のサイズは、 その派生型のすべてのコンポーネントを保持するために必要な バイト数の合計と等しくなります。

レコード構造体宣言を使用して宣言された順次派生型のサイズは、 その派生型のコンポーネントおよび埋め込みのすべてを保持するために必要な バイト数の合計と等しくなります。

以前は、共通ブロックにある数値順序または文字順序の構造体は、 そのコンポーネントが共通ブロック内で直接列挙されているかのように処理されていました。 現在は、これは、標準の派生型宣言を使用して宣言された型の構造体にのみ適用されます。

入出力

名前リスト入力では、構造体はその非充てん最終コンポーネントのリストに拡張されます。

名前リスト出力では、構造体はその非充てん最終コンポーネントの値に拡張されます。

定様式データ転送ステートメント (READWRITE、 または PRINT) では、%FILL コンポーネントではない 派生型のエンティティーのコンポーネントのみが input-item-list または output-item-list に 指定されているかのように処理されます。

派生型のエンティティー内の %FILL フィールドは、 不定形式データ転送ステートメントでは埋め込みとして扱われます。

派生型の型の決め方

2 つのデータ・オブジェクトを、同じ派生型定義を参照することによって 宣言している場合には、これらのデータ・オブジェクトの派生型は同じです。

これらのデータ・オブジェクトが別々の有効範囲単位内にある場合は、 両者が同じ派生型を持つことができます。 次の条件が満たされる場合は、ホスト関連付けまたは 使用関連付けを介して派生型定義にアクセスできるか、 またはデータ・オブジェクトが自己の派生型定義を参照します。

BIND 属性または SEQUENCE を指定する派生型定義は、プライベートと 宣言される定義、あるいはプライベートであるコンポーネントを持つ定義とは異なります。

派生型での型決定の例

PROGRAM MYPROG
 
TYPE NAME                         ! Sequence derived type
   SEQUENCE
   CHARACTER(20) LASTNAME
   CHARACTER(10) FIRSTNAME
   CHARACTER(1)  INITIAL
END TYPE NAME
TYPE (NAME) PER1
 
CALL MYSUB(PER1)
PER1 = NAME('Smith','John','K')   ! Structure constructor
CALL MYPRINT(PER1)
 
CONTAINS
  SUBROUTINE MYSUB(STUDENT)       ! Internal subroutine MYSUB
     TYPE (NAME) STUDENT          ! NAME is accessible via host association
              ...
  END SUBROUTINE MYSUB
END
 
SUBROUTINE MYPRINT(NAMES)         ! External subroutine MYPRINT
  TYPE NAME                       ! Same type as data type in MYPROG
     SEQUENCE
     CHARACTER(20) LASTNAME
     CHARACTER(10) FIRSTNAME
     CHARACTER(1)  INITIAL
  END TYPE NAME
  TYPE (NAME) NAMES               ! NAMES and PER1 from MYPROG
  PRINT *, NAMES                  ! have the same data type
END SUBROUTINE

異なるコンポーネント名の例

        MODULE MOD
          STRUCTURE /S/
           INTEGER I
           INTEGER, POINTER :: P
          END STRUCTURE
          RECORD /S/ R
        END MODULE
        PROGRAM P
          USE MOD, ONLY: R
          STRUCTURE /S/
            INTEGER J
            INTEGER, POINTER :: Q
          END STRUCTURE
          RECORD /S/ R2
          R = R2 ! OK - same type name, components have same attributes and
                 ! type (but different names)
        END PROGRAM P

構造体コンポーネント

構造体コンポーネントは、派生型も含めどの明示型でもかまいません。

注:
構造体コンポーネントが、配列または配列セクションである サブオブジェクトを持つ場合、配列セクションからの バックグラウンド情報が必要となります。 これについては、配列セクションおよび構造体コンポーネントに記述しています。 スカラー構造体コンポーネントに関する以下の規則は、 配列サブオブジェクトを持つ構造体コンポーネントにも適用されます。

コンポーネント指定子 を使って特定の構造体コンポーネントを参照することもできます。 スカラー・コンポーネント指定子は次のような構文を持ちます。

scalar_struct_comp:



>>-name--+---------------------+-------------------------------->
         '-(--int_expr_list--)-'
 
>--+--------------------------------------------------+--------->
   | .----------------------------------------------. |
   | V                                              | |
   '---separator comp_name--+---------------------+-+-'
                            '-(--int_expr_list--)-'
 
>--separator comp_name-+---------------------+-----------------><
                       '-(--int_expr_list--)-'
 
 

name
派生型のオブジェクトの名前です。

comp_name
派生型コンポーネントの名前です。

int_expr
添え字式と呼ばれるスカラー整数または実数式です。

separator
% または IBM 拡張の開始 . IBM 拡張の終了

構造体コンポーネントは、最右端の comp_name と 同様の型、型付きパラメーター、POINTER 属性 (もしあれば) を持ちます。 構造体コンポーネントは、親オブジェクト から INTENTTARGETPARAMETER などの属性を継承します。

注:

  1. comp_name は、直前の namecomp_name の いずれかのコンポーネントでなければなりません。

  2. 最右端を除く name および各 comp_name は、 派生型でなければなりません。

  3. int_expr_list 内の添え字式の数は、先行する name また は comp_name のランクと等しくなければなりません。

  4. name またはいずれかの comp_name が、 配列の名前である場合、int_expr_list を持たなければなりません。

  5. 最右端の comp_name は、スカラーでなければなりません。

名前リストのフォーマット設定では、区切り文字はパーセント記号でなければなりません。

区切り文字としてピリオドを使用する構造体コンポーネントであるか、 または 2 進演算であるかのいずれにでも解釈される形式が式に入っており、 その名前の演算子が有効範囲単位内でアクセス可能な場合、 XL Fortran はその式を 2 進演算として処理します。 それが意図した解釈ではない場合は、パーセント記号を使用してその部分を参照解除 するか、または、自由ソース形式であれば、ピリオドと comp_name の間に 空白を挿入してください。

構造体コンポーネントへの参照の例

例 1: 区切り文字としてのピリオドのあいまいな使用

        MODULE MOD
          STRUCTURE /S1/
            STRUCTURE /S2/ BLUE
              INTEGER I
            END STRUCTURE
          END STRUCTURE
          INTERFACE OPERATOR(.BLUE.)
            MODULE PROCEDURE BLUE
          END INTERFACE
        CONTAINS
          INTEGER FUNCTION BLUE(R1, I)
            RECORD /S1/ R1
            INTENT(IN) :: R1
            INTEGER, INTENT(IN) :: I
            BLUE = R1%BLUE%I + I
          END FUNCTION BLUE
        END MODULE MOD
 
        PROGRAM P
          USE MOD
          RECORD /S1/ R1
          R1%BLUE%I = 17
          I = 13
          PRINT *, R1.BLUE.I ! Calls BLUE(R1,I) - prints 30
          PRINT *, R1%BLUE%I ! Prints 17
        END PROGRAM P

例 2: 区切り文字の混合

        STRUCTURE /S1/
          INTEGER I
        END STRUCTURE
        STRUCTURE /S2/
          RECORD /S1/ C
        END STRUCTURE
        RECORD /S2/ R
        R.C%I = 17 ! OK
        R%C.I = 3 ! OK
        R%C%.I = 13 ! OK
        R.C.I = 19 ! OK
        END

例 3: 派生型でのパーセントとピリオドの機能

        STRUCTURE /S/
          INTEGER I, J
        END STRUCTURE
        TYPE DT
          INTEGER I, J
        END TYPE DT
        RECORD /S/ R1
        TYPE(DT) :: R2
        R1.I = 17; R1%J = 13
        R2.I = 19; R2%J = 11
        END

+----------------------------------IBM 拡張----------------------------------+

割り振り可能コンポーネント

ポインター・コンポーネントと同様、割り振り可能コンポーネントは 最終コンポーネントとして定義されます。 これは、値 (存在する場合) が残りの構造体とは別に保管され、構造体 の作成時にはこのストレージが存在しない (オブジェクトが 割り振り解除されているため) ためです。 最終ポインター・コンポーネントと同様、最終割り振り可能コンポーネントを含む変数は入出力リストに直接入れることは 禁止されています。

現在、割り振り可能配列と同様に、割り振り可能コンポーネントはストレージ関連付けコンテキストを 禁止されています。 このため、最終割り振り可能コンポーネントを含む変数は、 COMMON または EQUIVALENCE には入れることができません。 ただし、SEQUENCE 型には割り振り可能コンポーネントが許可されており、 同じ型を複数の有効範囲単位に別個に定義することが許されます。

最終割り振り可能コンポーネントを含む変数を割り振り解除すると、 現在割り振られている変数の割り振り可能コンポーネントが すべて自動的に割り振り解除されます。

割り振り可能コンポーネントを含む派生型の構造体コンストラクターでは、 割り振り可能コンポーネントに対応する式は以下のいずれかでなければなりません。

割り振り可能コンポーネントを含む派生型のオブジェクトの 組み込み割り当ての場合、左側にある変数の割り振り可能コンポーネントは、 割り振り状況と、割り振り済みである場合は式の対応するコンポーネントの 境界と値を受け取ります。 これは、次の順序でステップが実行されたかのように行われます。

  1. 変数のコンポーネントが現在割り振られている場合、 このコンポーネントが割り振り解除されます。
  2. 式の対応するコンポーネントが現在割り振り済みである場合、 変数のコンポーネントが同じ境界で割り振られます。 これで、式のコンポーネントの値が、組み込み割り当てを使用して 変数の対応するコンポーネントに割り当てられます。

INTENT(OUT) 仮引き数に関連した実引き数の 割り振り済み最終割り振り可能コンポーネントはプロシージャーに入るときに 割り振り解除され、仮引き数の対応するコンポーネントは、 現在割り振り済みでないという割り振り状況を持つようになります。

これにより、変数の割り振り可能コンポーネントの前の内容を指し示すポインターが、確実に未定義になります。

MODULE REAL_POLYNOMIAL_MODULE
  TYPE REAL_POLYNOMIAL
    REAL, ALLOCATABLE :: COEFF(:)
  END TYPE
  INTERFACE OPERATOR(+)
    MODULE PROCEDURE RP_ADD_RP, RP_ADD_R
  END INTERFACE
CONTAINS
  FUNCTION RP_ADD_R(P1,R)
    TYPE(REAL_POLYNOMIAL) RP_ADD_R, P1
    REAL R
    INTENT(IN) P1,R
    ALLOCATE(RP_ADD_R%COEFF(SIZE(P1%COEFF)))
    RP_ADD_R%COEFF = P1%COEFF
    RP_ADD_R%COEFF(1) = P1%COEFF(1) + R
  END FUNCTION
  FUNCTION RP_ADD_RP(P1,P2)
    TYPE(REAL_POLYNOMIAL) RP_ADD_RP, P1, P2
    INTENT(IN) P1, P2
    INTEGER M
    ALLOCATE(RP_ADD_RP%COEFF(MAX(SIZE(P1%COEFF), SIZE(P2%COEFF))))
    M = MIN(SIZE(P1%COEFF), SIZE(P2%COEFF))
    RP_ADD_RP%COEFF(:M) = P1%COEFF(:M) + P2%COEFF(:M)
    IF (SIZE(P1%COEFF)>M) THEN
      RP_ADD_RP%COEFF(M+1:) = P1%COEFF(M+1:)
    ELSE IF (SIZE(P2%COEFF)>M) THEN
      RP_ADD_RP%COEFF(M+1:) = P2%COEFF(M+1:)
    END IF
  END FUNCTION
END MODULE
 
PROGRAM EXAMPLE
  USE REAL_POLYNOMIAL_MODULE
  TYPE(REAL_POLYNOMIAL) P, Q, R
  P = REAL_POLYNOMIAL((/4,2,1/)) ! Set P to (X**2+2X+4)
  Q = REAL_POLYNOMIAL((/1,1/)) ! Set Q to (X+1)
  R = P + Q ! Polynomial addition
  PRINT *, 'Coefficients are: ', R%COEFF
END
 

+------------------------------End of IBM 拡張-------------------------------+

構造体コンストラクター



>>-type_name--(--expr_list--)----------------------------------><
 
 

type_name
派生型の名前です。

expr
式です。 式は、式および割り当てで定義されます。

構造体コンストラクターによって、値の番号付きリストから派生型の スカラー値を構成することができます。 構造体コンストラクターは、参照される派生型の定義の前に指定できません。

expr_list には、派生型のコンポーネントごとに 1 つの値が 含まれています。 expr_list の式の順序は、 数および順序の点で派生型のコンポーネントと一致していなければなりません。 それぞれの式の型と型付きパラメーターは、 対応するコンポーネントの型および型付きパラメーターと 整合性のある割り当てになっている必要があります。 データ型は、必要に応じて変換されます。

ポインターであるコンポーネントは、ポインターのコンポーネントと同じ型で宣言できます。 構造体コンストラクターがポインターを含む派生型に対して作成された場合、 ポインター・コンポーネントに対応する式は、ポインター割り当てステートメント内の そのようなポインターのために使用可能なターゲットとなり得るオブジェクトに 対して評価を行わなければなりません。

type_name、および、型のすべての コンポーネントは、構造体コンストラクターを含む有効範囲単位でアクセス可能でなければなりません。

+-------------------------Fortran 2003 ドラフト標準--------------------------+

派生型のコンポーネントが割り振り可能な場合、対応するコンストラクター式は、 引き数なしの組み込み関数 NULL() への参照になるか、割り振り可能エンティティーになるか、 あるいは対応するコンストラクター式の評価の結果が同じランクのエンティティーになります。 式が組み込み関数 NULL() への参照の場合、コンストラクターの 対応するコンポーネントは、現在割り振り済みでないという状況を持ちます。 式が割り振り可能エンティティーの場合、コンストラクターの対応するコンポーネントは、 割り振り可能エンティティーと同じ割り振り状況を持ち、割り振り済みである場合は、 同じ境界 (もしあれば) と値も持ちます。 そうでない場合は、コンストラクターの対応するコンポーネントは、 現在割り振り済みであるという割り振り状況と、 式と同じ境界 (もしあれば) および値を持ちます。

+----------------------End of Fortran 2003 ドラフト標準----------------------+

+----------------------------------IBM 拡張----------------------------------+

レコード構造宣言を使用するコンポーネントが %FILL の場合、 その型の構造体コンストラクターは使用できません。

派生型が有効範囲単位内でアクセス可能であり、 有効範囲単位内でアクセス可能な同じ名前の派生型ではないクラス 1 のローカル・エンティティーがある場合、 その型の構造体コンストラクターをその有効範囲内で使用することはできません。

+------------------------------End of IBM 拡張-------------------------------+

派生型の例

例 1:

MODULE PEOPLE
  TYPE NAME
     SEQUENCE                     ! Sequence derived type
     CHARACTER(20) LASTNAME
     CHARACTER(10) FIRSTNAME
     CHARACTER(1)  INITIAL
  END TYPE NAME
 
  TYPE PERSON                     ! Components accessible via use
                                  ! association
     INTEGER AGE
     INTEGER BIRTHDATE(3)         ! Array component
     TYPE (NAME) FULLNAME         ! Component of derived type
  END TYPE PERSON
END MODULE PEOPLE
 
PROGRAM TEST1
  USE PEOPLE
  TYPE (PERSON) SMITH, JONES
  SMITH = PERSON(30, (/6,30,63/), NAME('Smith','John','K'))
                                  ! Nested structure constructors
  JONES%AGE = SMITH%AGE           ! Component designator
  CALL TEST2
  CONTAINS
 
  SUBROUTINE TEST2
    TYPE T
      INTEGER EMP_NO
      CHARACTER, POINTER :: EMP_NAME(:)  ! Pointer component
    END TYPE T
    TYPE (T) EMP_REC
    CHARACTER, TARGET :: NAME(10)
    EMP_REC = T(24744,NAME)              ! Pointer assignment occurs
  END SUBROUTINE                         ! for EMP_REC%EMP_NAME
END PROGRAM

+---------------------------------Fortran 95---------------------------------+

例 2:

PROGRAM LOCAL_VAR
   TYPE DT
      INTEGER A
      INTEGER :: B = 80
   END TYPE
 
   TYPE(DT) DT_VAR                      ! DT_VAR%B IS INITIALIZED
END PROGRAM LOCAL_VAR

例 3:

MODULE MYMOD
   TYPE DT
      INTEGER :: A = 40
      INTEGER, POINTER :: B => NULL()
   END TYPE
END MODULE
 
PROGRAM DT_INIT
   USE MYMOD
   TYPE(DT), SAVE :: SAVED(8)            ! SAVED%A AND SAVED%B ARE INITIALIZED
   TYPE(DT) LOCAL(5)                     ! LOCAL%A LOCAL%B ARE INITIALIZED
END PROGRAM

+-----------------------------End of Fortran 95------------------------------+

+----------------------------------IBM 拡張----------------------------------+

レコード構造

レコード構造の宣言

レコード構造体を宣言すると、標準の FORTRAN 派生型定義でユーザー定義型を 宣言するのと同じ方法でユーザー定義型が宣言されます。 レコード構造体宣言を使用して宣言された型は派生型です。 多くの場合、標準の FORTRAN 構文を使用して宣言された派生型に 適用される規則は、レコード構造構文を使用して宣言された派生型に適用されます。 規則に違いがある場合、レコード構造宣言を使用して宣言された 派生型と、標準の派生型宣言を使用して宣言された派生型の 両者を参照するとその違いがわかります。

レコード構造宣言は、以下の構文に従って行います。

record_structure_dcl:



>>-structure_stmt----------------------------------------------><
 
 
   .----------------------.
   V                      |
>>---struct_comp_dcl_item-+------------------------------------><
 
 
>>-end_structure_stmt------------------------------------------><
 
 

struct_comp_dcl_item:

>>-+-component_def_stmt---+------------------------------------><
   +-record_structure_dcl-+
   '-parameter_stmt-------'
 
 

component_def_stmt は、派生型の コンポーネントを定義するために使用される型宣言ステートメントです。

structure_stmt:

>>-STRUCTURE--+------------------+--+--------------------+-----><
              '-/structure_name/-'  '-component_dcl_list-'
 
 

component_dcl:

>>-a--+----------------+---------------------------------------><
      '-(-array_spec-)-'
 
 

a はオブジェクト名です。

構造体ステートメントは、structure_name が、 それを囲む最も近いプログラム単位、インターフェース本体、 またはサブプログラムの有効範囲単位内の派生型であることを宣言します。 派生型は、その有効範囲単位内のクラス 1 のローカル・エンティティーです。

構造体ステートメントは別のレコード構造宣言内にネストされない限り、 component_dcl_list は指定されません。 同様に構造体ステートメントの structure_name は、別のレコード構造宣言内に ネストされている record_structure_dcl の一部でない限り省略できません。 record_structure_dcl は、少なくとも 1 つのコンポーネントを持っている必要があります。

レコード構造宣言を使用して宣言された派生型は、 順序派生型であり、順序派生型に適用されるすべての規則に従います。 標準派生型宣言を使用して宣言された順序派生型と同様に、 レコード構造宣言を使用して宣言された型のコンポーネントは、 非順序派生型にできません。 レコード構造宣言には、PRIVATE または SEQUENCE ステートメントを 入れることはできません。

レコード構造宣言は有効範囲単位を定義します。 record_structure_dcl にあるすべてのステートメントは、 レコード構造宣言の有効範囲単位の部分になります (record_structure_dcl に 含まれているその他の record_structure_dcl は例外)。 これらの規則は、標準の派生型宣言にも当てはまります。 明確にするために、以下で繰り返して説明します。

record_structure_dcl 内の parameter_stmt は、 それを囲む最も近いプログラム単位、インターフェース本体、 またはサブプログラムの有効範囲単位内にある名前付き定数を宣言します。 このような parameter_stmt で宣言された名前付き定数は、 この定数を含む record_structure_dcl で宣言された コンポーネントと同じ名前にできます。

structure_stmt で宣言されたコンポーネントはどれも、 それを囲む派生型のコンポーネントであり、 それを囲む構造体の有効範囲単位のローカル・エンティティーです。 このようなコンポーネントの型は、その structure_stmt で宣言される派生型です。

標準の派生型宣言を使用して宣言された派生型とは異なり、 レコード構造宣言を使用して宣言された派生型名は、 組み込み型の名前と同じ名前にできます。

レコード構造宣言の component_def_stmt には、 コンポーネントの名前の代わりに %FILL を使用できます。 %FILL コンポーネントは、レコード構造宣言において、 データを希望する位置に合わせるためのプレースホルダーとして使用されます。 初期化では、%FILL コンポーネントに関する指定はできません。 レコード構造宣言内の %FILL の各インスタンスは、型 に指定したその他のすべてのコンポーネント名と異なり、 しかもその他のすべての %FILL コンポーネントとも異なる、 固有のコンポーネント名として扱われます。 %FILL は 1 つのキーワードであり、-qmixed コンパイラー・オプションの影響は受けません。

名前を持たない、ネストされた構造体の各インスタンスは、 他のすべてのアクセス可能エンティティーの名前とは異なる 固有の名前を持っているものとして扱われます。

派生型についてこれまで説明した規則の延長として、レコード構造宣言を使用して宣言された派生型の 直接コンポーネントには、次のものがあります。

派生型の非充てん最終コンポーネントは、これも直接コンポーネントである 派生型の最終コンポーネントです。

デフォルトの初期化付きの派生型のオブジェクトは、共通ブロックのメンバーに指定できます。ただし、共通ブロックの初期化が、複数の有効範囲単位内で行われることがないようにする必要があります。

レコード構造の宣言の例

例 1: ネストされたレコード構造宣言 - 名前付きおよび名前なし

        STRUCTURE /S1/
          STRUCTURE /S2/ A ! A is a component of S1 of type S2
            INTEGER I
          END STRUCTURE
          STRUCTURE B ! B is a component of S1 of unnamed type
            INTEGER J
          END STRUCTURE
        END STRUCTURE
        RECORD /S1/ R1
        RECORD /S2/ R2 ! Type S2 is accessible here.
        R2.I = 17
        R1.A = R2
        R1.B.J = 13
        END

例 2: 構造体宣言内でネストされているパラメーター・ステートメント

        INTEGER I
        STRUCTURE /S/
          INTEGER J
          PARAMETER(I=17, J=13) ! Declares I and J in scope of program unit to
                                ! be named constants
        END STRUCTURE
        INTEGER J ! Confirms implicit typing of named constant J
        RECORD /S/ R
        R.J = I + J
        PRINT *, R.J ! Prints 30
        END

例 3: %FILL フィールド

        STRUCTURE /S/
          INTEGER I, %FILL, %FILL(2,2), J
          STRUCTURE /S2/ R1, %FILL, R2
            INTEGER I
          END STRUCTURE
        END STRUCTURE
        RECORD /S/ R
        PRINT *, LOC(R%J)-LOC(R%I)  ! Prints 24 with -qintsize=4
        PRINT *, LOC(R%R2)-LOC(R%R1) ! Prints 8 with -qintsize=4
        END

ストレージ・マッピング

レコード構造宣言を使用して宣言された派生型は、順序派生型です。 このような型のオブジェクトは、指定された順序でメモリーにコンポーネントを保管します。 標準の派生型宣言を使用して宣言された順序派生型の オブジェクトについてもこれと同じことが言えます。

-qalign オプションは、ストレージ内でのデータ・オブジェクトの位置合わせを指定します。 これにより、誤って位置合わせされたデータによるパフォーマンス上の問題が回避されます。 [no]4kstruct の両方のサブオプションを指定でき、 相互に排他的ではありません。 デフォルトの設定は -qalign=no4k:struct=natural です。 [no]4K は、主に、論理ボリューム入出力とディスク・ストライピングの組み合わせで役に立ちます。

+------------------------------End of IBM 拡張-------------------------------+

+----------------------------------IBM 拡張----------------------------------+

UNION および MAP

UNION は、プログラム内のデータ域を共有できる、それを囲むレコード構造の中にフィールド・グループを宣言します。

UNION および MAP は次の構文に従います。

union_dcl:



          .----------------.
          V                |
>>-UNION----union_dcl_item-+-----------------------------------><
 
 
>>-END UNION---------------------------------------------------><
 
 

union_dcl_item:

>>-+-map_dcl--------+------------------------------------------><
   '-parameter_stmt-'
 
 

map_dcl:



        .--------------.
        V              |
>>-MAP----map_dcl_item-+---------------------------------------><
 
 
>>-END MAP-----------------------------------------------------><
 
 

map_dcl_item:

>>-+-struct_comp_dcl_item-+------------------------------------><
   '-record_stmt----------'
 
 

struct_comp_dcl_item:

>>-+-component_def_stmt---+------------------------------------><
   +-record_structure_dcl-+
   +-parameter_stmt-------+
   '-union_dcl------------'
 
 

UNION 宣言はレコード構造内に定義する必要があり、 MAP 宣言の中に入れることが可能です。 また、MAP 宣言は UNION 宣言内になければなりません。 UNION 宣言内の map_dcl_item にあるすべての宣言は、 宣言がどの map_dcl にあるのかにかかわらず同じネスト・レベルに なっていなければなりません。 このため、map_dcl 内のコンポーネント名を、 同じレベルの他の map_dcl に入れることができません。

map 宣言内で宣言されたコンポーネントには、 POINTERFORTRAN 2003 の開始 PRIVATEPUBLIC、または ALLOCATABLE FORTRAN 2003 の終了 属性があってはなりません。

UNION MAP を持つレコード構造は I/O ステートメントには使用できません。

MAP 宣言で宣言されたコンポーネントは、UNION 構文内の その他の MAP 宣言で宣言されたコンポーネントと同じストレージを共用します。 ある MAP 宣言内にある 1 つのコンポーネントに値を割り当てると、 ストレージをこのコンポーネントと共用する、その他の MAP 宣言内の コンポーネントが影響を受けます。

MAP のサイズは、MAP 内で宣言されたコンポーネントの合計サイズです。

UNION 宣言で確立されるデータ域のサイズは、その UNION で 定義された最大 MAP のサイズです。

MAP 宣言または UNION 構文にある parameter_stmt は、 最も近いこれを囲むプログラム単位、インターフェース本体、またはサブプログラムの 有効範囲単位内でエンティティーを宣言します。

MAP 宣言にある %FILL フィールドは、 レコード構成で目的に合ったデータの位置合わせを行うための プレースホルダーとして使用されます。 その他の非充てんコンポーネント、またはデータ域を %FILL フィールドと 共用する、その他の map 宣言内のコンポーネントの一部は未定義です。

UNION 宣言内の少なくとも 1 つの MAP にある component_def_stmts に デフォルトの初期化が指定されている場合、初期化の最後のオカレンスは コンポーネントの最終初期化になります。

レコード構造内の UNION MAP 宣言のいずれかにデフォルトの初期化が指定されている場合、 デフォルトで割り当てられたストレージ・クラスを持つ型の変数には、以下のいずれかのストレージ・クラスが与えられます。

常に 1 つの MAP のみが共用ストレージに関連します。 別の MAP からのコンポーネントが参照される場合、 関連した MAP が関連解除され、そのコンポーネントは未定義になります。 これで、参照されている MAP がストレージに関連させられます。

map_dcl のコンポーネントが UNION 内のその他の map_dcl%FILL コンポーネントに完全にまたは部分的にマップされている場合、 そのコンポーネントがデフォルトの初期化か、または割り当てステートメントによって 初期化されない限り、オーバーラップ部分の値は未定義です。

UNION および MAP の例

例 1: UNION のサイズは、その UNION 内の最大 MAP のサイズと同じです

     structure /S/
        union
          map
            integer*4  i, j, k
            real*8  r, s, t
          end map
          map
            integer*4  p, q
            real*4  u, v
          end map
        end union         ! Size of the union is 36 bytes.
      end structure
      record /S/ r

例 2: 別の -qsave オプションおよびサブオプションを使用すると、UNION MAP の結果は異なります

      PROGRAM P
       CALL SUB
       CALL SUB
      END PROGRAM P
 
      SUBROUTINE SUB
        LOGICAL, SAVE :: FIRST_TIME = .TRUE.
        STRUCTURE /S/
          UNION
            MAP
              INTEGER I/17/
            END MAP
            MAP
              INTEGER J
            END MAP
          END UNION
        END STRUCTURE
        RECORD /S/ LOCAL_STRUCT
        INTEGER LOCAL_VAR
 
        IF (FIRST_TIME) THEN
          LOCAL_STRUCT.J = 13
          LOCAL_VAR = 19
          FIRST_TIME = .FALSE.
        ELSE
          ! Prints " 13" if compiled with -qsave or -qsave=all
          ! Prints " 13" if compiled with -qsave=defaultinit
          ! Prints " 17" if compiled with -qnosave
          PRINT *, LOCAL_STRUCT%j
          ! Prints " 19" if compiled with -qsave or -qsave=all
          ! Value of LOCAL_VAR is undefined otherwise
          PRINT *, LOCAL_VAR
        END IF
      END SUBROUTINE SUB

例 3: UNION 構造内の MAP 宣言にあるデフォルトの初期化の 最後のオカレンスは、コンポーネントの最終初期化になります

        structure /st/
          union
            map
              integer  i /3/, j /4/
              union
                map
                  integer  k /8/, l /9/
                end map
              end union
            end map
            map
              integer  a, b
              union
                map
                  integer  c /21/
                end map
              end union
            end map
          end union
        end structure
        record /st/ R
        print *, R.i, R.j, R.k, R.l      ! Prints "3 4 21 9"
        print *, R.a, R.b, R.c           ! Prints "3 4 21"
        end

例 4: 次のプログラムは -qintsize=4 および -qalign=struct=packed でコンパイルされます。 UNION MAP 内のコンポーネントは位置合わせされてパックされます

        structure /s/
          union
            map
              integer*2  i /z'1a1a'/, %FILL, j /z'2b2b'/
            end map
            map
              integer  m, n
            end map
          end union
        end structure
        record /s/ r
 
        print '(2z6.4)', r.i, r.j      ! Prints "1A1A  2B2B"
        print '(2z10.8)', r.m, r.n     ! Prints "1A1A0000  2B2B0000" however
                                       ! the two bytes in the lower order are
                                       ! not guaranteed.
        r.m = z'abc00cba'              ! Components are initialized by
                                       ! assignment statements.
        r.n = z'02344320'
 
        print '(2z10.8)', r.m, r.n     ! Prints "ABC00CBA  02344320"
        print '(2z6.4)', r.i, r.j      ! Prints "ABC0  0234"
        end

+------------------------------End of IBM 拡張-------------------------------+

IBM Copyright 2003