派生型として認識される追加のデータ型は、 組み込みデータ型や他の派生型から作成することができます。 派生型の名前 (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------------------------------------------>< |
+---------------------------------Fortran 95---------------------------------+
さらに、Fortran 95 では、派生型の定義の 各コンポーネントに対して、デフォルトの初期化を指定することができます。 詳細な構文および説明に関しては、 型宣言を参照してください。
+-----------------------------End of Fortran 95------------------------------+
+---------------------------------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 で、デフォルトの初期化の候補となるデータ・オブジェクトは、 以下のような名前付きデータ・オブジェクトです。
非ポインターかつ割り振り不可能なコンポーネントのデフォルトの初期化は、 その型の直接コンポーネントに対して行われるどのデフォルト初期化よりも優先します。
仮引き数に 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------------------------------+
標準の派生型宣言を使用して宣言された順次派生型のサイズは、 その派生型のすべてのコンポーネントを保持するために必要な バイト数の合計と等しくなります。
レコード構造体宣言を使用して宣言された順次派生型のサイズは、 その派生型のコンポーネントおよび埋め込みのすべてを保持するために必要な バイト数の合計と等しくなります。
以前は、共通ブロックにある数値順序または文字順序の構造体は、 そのコンポーネントが共通ブロック内で直接列挙されているかのように処理されていました。 現在は、これは、標準の派生型宣言を使用して宣言された型の構造体にのみ適用されます。
名前リスト入力では、構造体はその非充てん最終コンポーネントのリストに拡張されます。
名前リスト出力では、構造体はその非充てん最終コンポーネントの値に拡張されます。
定様式データ転送ステートメント (READ、WRITE、 または 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--)-' |
構造体コンポーネントは、最右端の comp_name と 同様の型、型付きパラメーター、POINTER 属性 (もしあれば) を持ちます。 構造体コンポーネントは、親オブジェクト から INTENT、TARGET、PARAMETER などの属性を継承します。
注:
名前リストのフォーマット設定では、区切り文字はパーセント記号でなければなりません。
区切り文字としてピリオドを使用する構造体コンポーネントであるか、 または 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 型には割り振り可能コンポーネントが許可されており、 同じ型を複数の有効範囲単位に別個に定義することが許されます。
最終割り振り可能コンポーネントを含む変数を割り振り解除すると、 現在割り振られている変数の割り振り可能コンポーネントが すべて自動的に割り振り解除されます。
割り振り可能コンポーネントを含む派生型の構造体コンストラクターでは、 割り振り可能コンポーネントに対応する式は以下のいずれかでなければなりません。
割り振り可能コンポーネントを含む派生型のオブジェクトの 組み込み割り当ての場合、左側にある変数の割り振り可能コンポーネントは、 割り振り状況と、割り振り済みである場合は式の対応するコンポーネントの 境界と値を受け取ります。 これは、次の順序でステップが実行されたかのように行われます。
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--)---------------------------------->< |
構造体コンストラクターによって、値の番号付きリストから派生型の スカラー値を構成することができます。 構造体コンストラクターは、参照される派生型の定義の前に指定できません。
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]4k と struct の両方のサブオプションを指定でき、 相互に排他的ではありません。 デフォルトの設定は -qalign=no4k:struct=natural です。 [no]4K は、主に、論理ボリューム入出力とディスク・ストライピングの組み合わせで役に立ちます。
+------------------------------End of IBM 拡張-------------------------------+
+----------------------------------IBM 拡張----------------------------------+
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、
PRIVATE、PUBLIC、または 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 コンポーネントに完全にまたは部分的にマップされている場合、 そのコンポーネントがデフォルトの初期化か、または割り当てステートメントによって 初期化されない限り、オーバーラップ部分の値は未定義です。
例 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 拡張-------------------------------+