A structure is a generalization of an array. @
Just as an array is a collection of elements of the same type, a structure is a collection of elements that are not necessarily of the same type.
As elements of arrays are referenced by using numeric subscripts, so elements of structures are referenced by using element (or field) names.
The structure declaration defines the form of a record by specifying the name, type, size, and order of the fields that constitute the record. Once a structure is defined and named, it can be used in RECORD statements, as explained in the following subsections.
The structure declaration has the following syntax:
STRUCTURE [/structure-name/] [field-list] field-declaration [field-declaration] . . . [field-declaration] END STRUCTURE | |
---|---|
structure-name |
Name of the structure |
field-list |
List of fields of the specified structure |
field-declaration |
Defines a field of the record. field-declaration is defined in the next section. |
Each field declaration can be one of the following:
A substructure--either another structure declaration, or a record that has been previously defined
A union declaration, which is described later
A FORTRAN type declaration
Example: A STRUCTURE declaration:
STRUCTURE /PRODUCT/ INTEGER*4 ID CHARACTER*16 NAME CHARACTER*8 MODEL REAL*4 COST REAL*4 PRICE END STRUCTURE
In the above example, a structure named PRODUCT is defined to consist of the five fields ID, NAME, MODEL, COST, and PRICE. For an example with a field-list, see "Structure within a Structure ".
Note the following:
The name is enclosed in slashes, and is optional only in nested structures.
If slashes are present, a name must be present.
You can specify the field-list within nested structures only.
There must be at least one field-declaration.
Each structure-name must be unique among structures, although you can use structure names for fields in other structures or as variable names.
The only statements allowed between the STRUCTURE statement and the END STRUCTURE statement are field-declaration statements and PARAMETER statements. A PARAMETER statement inside a structure declaration block is equivalent to one outside.
Fields that are type declarations use the identical syntax of normal FORTRAN type statements. All f77 types are allowed, subject to the following rules and restrictions:
Any dimensioning needed must be in the type statement. The DIMENSION statement has no effect on field names.
You can specify the pseudo-name %FILL for a field name. %FILL is provided for compatibility with other versions of FORTRAN. It is not needed in f77 because the alignment problems are taken care of for you. It may be a useful feature if you want to make one or more fields that you cannot reference in some particular subroutine. The only thing that %FILL does is provide a field of the specified size and type, and preclude referencing it.
You must explicitly type all field names. The IMPLICIT statement does not apply to statements in a STRUCTURE declaration, nor do the implicit I,J,K,L,M,N rules apply.
You cannot use arrays with adjustable or assumed size in field declarations, nor can you include passed-length CHARACTER declarations.
In a structure declaration, the offset of field n is the offset of the preceding field, plus the length of the preceding field, possibly corrected for any adjustments made to maintain alignment. See Appendix C, Data Representations for a summary of storage allocation.
The RECORD statement declares variables to be records with a specified structure, or declares arrays to be arrays of such records.
The syntax of a RECORD statement is:
RECORD /structure-name/ record-list [,/structure-name/ record-list] [,/structure-name/ record-list] | |
---|---|
structure-name | Name of a previously declared structure |
record-list |
List of variables, arrays, or arrays with dimensioning and index ranges, separated by commas. |
Example: A RECORD that uses the previous STRUCTURE example:
RECORD /PRODUCT/ CURRENT, PRIOR, NEXT, LINE(10)
Each of the three variables, CURRENT, PRIOR, and NEXT, is a record which has the PRODUCT structure; LINE is an array of 10 such records.
Note the following rules and restrictions for records:
Each record is allocated separately in memory.
Initially, records have undefined values, unless explicitly initialized.
Records, record fields, record arrays, and record-array elements are allowed as arguments and dummy arguments. When you pass records as arguments, their fields must match in type, order, and dimension. The record declarations in the calling and called procedures must match. Within a union declaration, the order of the map fields is not relevant. See "Unions and Maps ".
Record fields are not allowed in COMMON statements.
Records and record fields are not allowed in DATA, EQUIVALENCE, or NAMELIST statements. Record fields are not allowed in SAVE statements.
You can refer to a whole record, or to an individual field in a record, and since structures can be nested, a field can itself be a structure, so you can refer to fields within fields, within fields, and so forth.
The syntax of record and field reference is:
record-name[.field-name] ... [.field-name] | |
---|---|
record-name |
Name of a previously defined record variable |
field-name |
Name of a field in the record immediately to the left. |
Example: References that are based on structure and records of the above two examples:
... RECORD /PRODUCT/ CURRENT, PRIOR, NEXT, LINE(10) ... CURRENT = NEXT LINE(1) = CURRENT WRITE ( 9 ) CURRENT NEXT.ID = 82
In the above example:
The first assignment statement copies one whole record (all five fields) to another record.
The second assignment statement copies a whole record into the first element of an array of records.
The WRITE statement writes a whole record.
The last statement sets the ID of one record to 82.
Example: Structure and record declarations, record and field assignments:
demo% cat str1.f * str1.f Simple structure STRUCTURE / S / INTEGER*4 I REAL*4 R END STRUCTURE RECORD / S / R1, R2 R1.I = 82 R1.R = 2.7182818 R2 = R1 WRITE ( *, * ) R2.I, R2.R STOP END demo% f77 -silent str1.f demo% a.out 82 2.718280 demo%
A structure can have a field that is also a structure. Such a field is called a substructure. You can declare a substructure in one of two ways:
A RECORD declaration within a structure declaration
A structure declaration within a structure declaration (nesting)
A nested structure declaration is one that is contained within either a structure declaration or a union declaration. You can use a previously defined record within a structure declaration.
Example: Define structure SALE using previously defined record PRODUCT:
STRUCTURE /SALE/ CHARACTER*32 BUYER INTEGER*2 QUANTITY RECORD /PRODUCT/ ITEM END STRUCTURE
In the above example, the structure SALE contains three fields, BUYER, QUANTITY, and ITEM, where ITEM is a record with the structure, /PRODUCT/.
You can nest a declaration within a declaration.
Example: If /PRODUCT/ is not declared previously, then you can declare it within the declaration of SALE:
STRUCTURE /SALE/ CHARACTER*32 BUYER INTEGER*2 QUANTITY STRUCTURE /PRODUCT/ ITEM INTEGER*4 ID CHARACTER*16 NAME CHARACTER*8 MODEL REAL*4 COST REAL*4 PRICE END STRUCTURE END STRUCTURE
Here, the structure SALE still contains the same three fields as in the prior example: BUYER, QUANTITY, and ITEM. The field ITEM is an example of a field-list (in this case, a single-element list), as defined under "Structure Declaration."
The size and complexity of the various structures determine which style of substructure declaration is best to use in a given situation.
You can refer to fields within substructures.
Example: Refer to fields of substructures (PRODUCT and SALE, from the previous examples, are defined in the current program unit):
... RECORD /SALE/ JAPAN ... N = JAPAN.QUANTITY I = JAPAN.ITEM.ID ...
Note the following:
You must define at least one field name for any substructure.
No two fields at the same nesting level can have the same name. Fields at different levels of a structure can have the same name; however, doing so might be questionable programming practice.
You can use the pseudo-name, %FILL, to align fields in a record, and create an unnamed empty field.
You must not include a structure as a substructure of itself, at any level of nesting.
A union declaration defines groups of fields that share memory at runtime.
The syntax of a union declaration is:
UNION map-declaration map-declaration [map-declaration ] ... [map-declaration ] END UNION
The syntax of a map declaration is as follows.
MAP field-declaration [field-declaration] ... [field-declaration] END MAP
Each field-declaration in a map declaration can be one of the following:
Structure declaration
Record
Union declaration
Declaration of a typed data field
A map declaration defines alternate groups of fields in a union. During execution, one map at a time is associated with a shared storage location. When you reference a field in a map, the fields in any previous map become undefined and are succeeded by the fields in the map of the newly referenced field. The amount of memory used by a union is that of its biggest map.
Example: Declare the structure /STUDENT/ to contain either NAME, CLASS, and MAJOR--or NAME, CLASS, CREDITS, and GRAD_DATE:
STRUCTURE /STUDENT/ CHARACTER*32 NAME INTEGER*2 CLASS UNION MAP CHARACTER*16 MAJOR END MAP MAP INTEGER*2 CREDITS CHARACTER*8 GRAD_DATE END MAP END UNION END STRUCTURE
If you define the variable PERSON to have the structure /STUDENT/ from the above example, then PERSON.MAJOR references a field from the first map, and PERSON.CREDITS references a field from the second map. If the variables of the second map field are initialized, and then the program references the variable PERSON.MAJOR, the first map becomes active, and the variables of the second map become undefined.