XL Fortran for AIX V8.1.1

ランゲージ・リファレンス


派生型

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

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

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

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

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

+--------------------------------IBM 拡張の終り-------------------------------+



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

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

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

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

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

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

+------------------------------Fortran 95 の終り------------------------------+

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

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

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

+------------------------------Fortran 95 の終り------------------------------+

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

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

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

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

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

順序派生型のサイズは、その派生型のすべてのコンポーネントを保持するために必要なストレージのバイト数に等しくなります。

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

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

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

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

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

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

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

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

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

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

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

非ポインター・コンポーネントのデフォルトの初期化は、そのタイプの直接コンポーネントに対して行われるどのデフォルト初期化よりも優先します。

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

+------------------------------Fortran 95 の終り------------------------------+

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

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

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

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

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

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

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

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

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

+------------------------------Fortran 95 の終り------------------------------+

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

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

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

入出力

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

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

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

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

派生型のタイプの決め方

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

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

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 拡張です。

構造体コンポーネントは、最右端の 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
 

+--------------------------------IBM 拡張の終り-------------------------------+

構造体コンストラクター



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

type_name
派生型の名前です。

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

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

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

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

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

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

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

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

+--------------------------------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

+------------------------------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 は、主に、論理ボリューム入出力とディスク・ストライピングの組み合わせで役に立ちます。

+--------------------------------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 宣言内で宣言されるコンポーネントには POINTER または ALLOCATABLE 属性があってはいけません。

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=pack でコンパイルされます。 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

+--------------------------------IBM 拡張の終り-------------------------------+


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]