Chapter 6. Using Data

Chapter 5, “Declarations”, explains how data objects are created and how their attributes are specified. This chapter explains how these objects can be used. The appearance of the name or designator where its value is required is a reference to the object. When an object is referenced, it must be defined; that is, it must have a value. The reference makes use of the value. Consider the following two statements:

A = 1.0
B = A + 4.0

In the first statement, the constant value 1.0 is assigned to the variable A. It does not matter whether A was previously defined with a value or not; it now has a value and can be referenced in an executable statement. In the second statement, A is referenced; its value is obtained and added to the constant 4.0 to obtain a value that is then assigned to the variable B. The appearances of A in the first statement and B in the second statement are not considered to be references because their values are not required. The appearance of A in the second statement is a reference.

A data object can be a constant or a variable. Variables and constants can be scalar objects (with a single value) or arrays (with any number of values, all of the same type). Strictly speaking, there is no such thing as an array constant. An array constructor made up of all constant values is a constant expression, not an array constant. Also note that a derived type is a scalar value. Similar to an array constructor, a derived type constructor composed of all constant values is a constant expression, not a structure constant.

Arrays are said to be dynamic if their size can change. Automatic arrays are discussed in “Automatic Data Objects” in Chapter 5; they are created on entry to a procedure, and their sizes are determined at that time. Allocatable arrays or pointer arrays can change size as well. The declared rank cannot change, but the extents of the dimensions may change with each reallocation or pointer assignment.

If a variable or constant is a portion of another object, it is called a subobject. A subobject can be one of the following items:

A variable is referenced by its name, whereas a subobject is referenced by a designator. A designator indicates the portion of an object that is being referenced. Each subobject is considered to have a parent and is a portion of the parent. Each of the subobjects is described in this chapter.

This chapter also explains how to create and release pointers and allocatable arrays by using the ALLOCATE and DEALLOCATE statements. In addition, you can disassociate pointers from any target object by using the NULLIFY statement.

A reference to a variable or subobject is called a data reference. Guidelines exist for determining whether a particular data reference is classified as a character string, character substring, structure component, array, array element, or array section. These classifications are perhaps of more interest to compiler writers than to users of the language, but knowing how a data reference is classified makes it clearer which rules and restrictions apply to the reference, and easier to understand some of the explanations for the formation of expressions. Briefly, character strings and substrings must be of type character. Arrays have the DIMENSION attribute. Some data references can be classified as both structure components and array sections. In general, if a data reference contains a percent sign (%), it is a structure component, but its actual classification can be determined by other factors such as a section subscript or the rightmost element of the reference. If a substring range appears in a data reference, it must appear at the right end of the reference; the reference is considered to be a substring unless some component of the reference is an array section, in which case the data reference is considered to be an array section that just happens to have elements that are substrings. For a component reference to be classified as an array element, every component must have rank zero and a subscript list must appear at the right end of the reference. “Constants and Variables”, through “Format of Array Elements and Array Sections”, contain many examples that demonstrate how these guidelines for classification apply.

Constants and Variables

A constant has a value that cannot change; it can be a literal constant or a named constant (parameter). As explained in Chapter 4, “Data Types”, each of the intrinsic types has a form that specifies the type, type parameters, and value of a literal constant of the type. For user-defined types, there is a structure constructor to specify values of the type. If all of the components of a structure constructor are constants, the resulting derived-type value is a constant expression. Array constructors are used to form array values of any intrinsic or user-defined type. If all array elements are constant values, the resulting array is a constant array expression. A reference to a constant is always permitted.

A variable has a name such as A or a designator such as B(I), and may or may not have a value. If it does not have a value, it must not be referenced. Variables are defined as follows:

 

variable

is

scalar_variable_name

 

 

or

array_variable_name

 

 

or

subobject

 

subobject

is

array_element

 

 

or

array_section

 

 

or

structure_component

 

 

or

substring

 

logical_variable

is

variable

 

default_logical_variable

is

variable

 

char_variable

is

variable

 

default_char_variable

is

variable

 

int_variable

is

variable

 

default_int_variable

is

variable

A logical_variable must be of type logical, and a default_logical_variable must be of type default logical. A char_variable must be of type character and a default_char_variable must be of type default character. The CF90 and MIPSpro 7 Fortran 90 compilers do not support any nondefault character types. An int_variable must be of type integer and a default_int_variable must be of type default integer.

Variables can be of any type, except for Boolean (typeless). There are contexts in which a variable must be of a certain type. In some of these cases, terms, such as logical_variable, character_variable, or Cray pointer, provide precise limitations.


Note: The Fortran standard does not specify Boolean (typeless) constants or Cray pointers.

A subobject with a constant parent is not a variable.

A single object of any of the intrinsic or user-defined types is a scalar. A set of scalar objects, all of the same type and type parameters, can be arranged in a pattern involving columns, rows, planes, and higher-dimensioned configurations to form an array. An array has a rank between one and seven. A scalar has rank zero. In simple terms, an array is an object with the DIMENSION attribute; a scalar is not an array. For example:

TYPE PERSON
   INTEGER AGE
   CHARACTER(LEN = 40) NAME
END TYPE PERSON

TYPE(PERSON) FIRECHIEF, FIREMEN(50)
CHARACTER*(20) DISTRICT, STATIONS(10)

The following data references are classified as indicated by the comments on each line:

DISTRICT      ! character string
DISTRICT(1:6) ! substring
FIRECHIEF%AGE ! structure component
FIREMEN%AGE   ! array of integers
STATIONS      ! array of character strings
STATIONS(1)   ! array element (character string)
STATIONS(1:4) ! array section of character strings

The following code segment shows that a subobject can have a constant parent:

CHARACTER(*), PARAMETER :: MY_DISTRICT = "DISTRICT 13"
CHARACTER(2) DISTRICT_NUMBER
DISTRICT_NUMBER = MY_DISTRICT(10:11)

DISTRICT_NUMBER has the value 13.

Substrings

A character string consists of zero or more characters. Even though it is made up of individual characters, a character string is considered to be scalar. As with any data type, it is possible to declare an array of character strings, all of the same length.

A substring is a contiguous portion of a character string that has a starting point and an ending point within the character string. It is possible to reference a substring of a character variable or constant.

Substrings are defined as follows:

 

substring

is

parent_string (substring_range)

 

parent_string

is

scalar_variable_name

 

 

or

array_element

 

 

or

scalar_structure_component

 

 

or

scalar_constant

 

substring_range

is

[scalar_int_expr] : [scalar_int_expr]

The parent_string of a substring must be of type character. The substring is of type character.

The scalar_int_expr at the left in the substring_range is the starting position. The scalar_int_expr at the right in the substring_range is the ending position.

A substring is the contiguous sequence of characters within the string, beginning with the character at the starting position and ending at the ending position. If the starting position is omitted, the default is 1; if the ending position is omitted, the default is the length of the character string.

The length of a character string or substring can be 0, but not a negative number. Zero-length strings result when the starting position is greater than the ending position. The formula for calculating the length of a string is as follows:

MAX (ending_position - starting_position + 1, 0)

The first character of a parent string is at position 1 and the last character is at position n where n is the length of the string. The starting position of a substring must be greater than or equal to 1 and the ending position must be less than or equal to the length n, unless the length of the substring is 0. If the parent string is of length 0, the substring must be of length 0.

Example 1:

CHARACTER*(14) NAME
NAME = "John Q. Public"
NAME(1:4) = "Jane"
PRINT *, NAME(9:14)

In example 1, NAME is a scalar character variable, a string of 14 characters, that is assigned the value John Q. Public by the first assignment statement. NAME(1:4) is a substring of four characters that is reassigned the value Jane by the second assignment statement, leaving the remainder of the string NAME unchanged; the string NAME then becomes Jane Q. Public. The PRINT statement prints the characters in positions 9 through 14, in this case, the surname, Public.

Example 2:

Assume the following definition and declarations:

TYPE PERSON
   INTEGER AGE
   CHARACTER(LEN = 40) NAME
END TYPE PERSON

TYPE(PERSON) FIRECHIEF, FIREMEN(50)
CHARACTER(20) DISTRICT, STATIONS(10)

The following are all substrings:

STATIONS(1)(1:5)    ! array element as parent string
FIRECHIEF%NAME(4:9) ! structure component as parent string
DISTRICT(7:14)      ! scalar variable as parent string
'0123456789'(N:N+1) ! character constant as parent string

In example 2, the reference STATIONS(:)(1:5) is permitted. It is an array whose elements are substrings, but it is not considered to be a substring reference. Even though the entire array is indicated, this reference is considered to be an array section reference. The description is in “Format of Array Elements and Array Sections”. STATIONS(1:5)(1:5) is also permitted. It is an array section whose elements are substrings. Whenever an array is constructed of character strings and any part of it (other than the whole object) is referenced, an array section subscript must appear before the substring range specification, if any. Otherwise, the substring range specification will be treated as an array section specification because the two have the same form. STATIONS(1:5) is an array section reference that references the entire character strings of the first five elements of STATIONS. The last line of the example is a substring where the parent is a constant and the starting and ending positions are variable.

Structure Components

A structure is an aggregate of components of intrinsic or derived types. It is itself an object of derived type. The types and attributes of the components are specified in the type definition; they can be scalars or arrays. Each structure has at least one component. There can be arrays of structures. In example 2 (see “Substrings”), FIRECHIEF is a structure; FIREMEN is an array of structures of type PERSON.

A component of a structure is referenced by placing the name of the component after the name of the parent structure, separated by a percent sign (%). For example, FIRECHIEF % NAME references the character string component of the variable FIRECHIEF of type PERSON.

A structure component is a data reference and is defined as follows:

 

data_ref

is

part_ref[ % part_ref] ...

 

part_ref

is

part_name[ (section_subscript_list) ]

 

structure_component

is

data_ref

For a data reference to be considered a structure component reference, there must be more than one part reference and the rightmost part reference must be a part name. If the rightmost component is of the following form, the reference is considered to be an array section or array element (the simplest form of a section subscript list is a subscript list):

part_name (section_subscript_list)

The rules for forming a section_subscript_list and a subscript are provided in “Arrays”.

In a data reference, each part name except the rightmost must be of derived type.

In a data reference, each part name except the leftmost must be the name of a component of the derived-type definition of the type of the preceding part name.

In a part reference containing a section subscript list, the number of section subscripts must equal the rank of the part name.

It is possible to create a structure with more than one array part, but in a data reference to the structure, there must not be more than one part reference with nonzero rank.

In a data reference, a part name to the right of a part reference with nonzero rank must not have the POINTER attribute. It is possible to declare an array of structures that have a pointer as a component, but it is not possible to reference such an object as an array.

The rank of a part reference consisting of just a part name is the rank of the part name. The rank of a part reference of the following form is the number of subscript triplets and vector subscripts in the list:

part_name (section_subscript_list)

The rank is less than the rank of the part name if any of the section subscripts are subscripts other than subscript triplets or vector subscripts. The shape of a data reference is the shape of the part reference with nonzero rank, if any; otherwise, the data reference is a scalar and has rank zero.

The parent structure in a data reference is the data object specified by the leftmost part name. If the parent object has the INTENT, TARGET, or PARAMETER attribute, the structure component has the attribute. The type and type parameters of a structure component are those of the rightmost part name. A structure component is a pointer only if the rightmost part name has the POINTER attribute. Typically, an object cannot have both the TARGET and POINTER attributes. However, a structure that has the TARGET attribute can contain components that have the POINTER attribute.

Example 1: Assume the following type definition and structure declarations:

TYPE PERSON
   INTEGER AGE
   CHARACTER(LEN = 40) NAME
END TYPE PERSON
. . .
TYPE(PERSON) FIRECHIEF, FIREMEN(50)

In this example, structure components are as follows:

FIRECHIEF%AGE    ! scalar component of scalar parent
FIREMEN(J)%NAME  ! component of array element parent
FIREMEN(1:N)%AGE ! component of array section parent

Example 2: If a derived-type definition contains a component that is of derived type, then a reference to an ultimate component can contain more than two part references as do the references in the first two PRINT statements in the following example:

TYPE REPAIR_BILL
   REAL PARTS
   REAL LABOR
END TYPE REPAIR_BILL
. . .
TYPE VEHICLE
   CHARACTER(LEN = 40) OWNER
   INTEGER MILEAGE
   TYPE(REPAIR_BILL) COST
END TYPE VEHICLE
. . .
TYPE(VEHICLE) BLACK_FORD, RED_FERRARI
. . .
PRINT *, BLACK_FORD%COST%PARTS
PRINT *, RED_FERRARI%COST%LABOR
PRINT *, RED_FERRARI%OWNER

Arrays

An array is a collection of scalar elements of any intrinsic or derived type. An object of any type that is specified to have the DIMENSION attribute is an array. All of the elements of an array must have the same type and kind parameter. There can be arrays of structures. The value returned by a function can be an array. The appearance of an array name or designator has no implications for the order in which the individual elements are referenced unless array element ordering is specifically required.

Array Terminology

An array consists of elements that extend in one or more dimensions to represent columns, rows, planes, and so on. There can be up to seven dimensions in an array declaration. The number of dimensions in an array is called the rank of the array. The number of elements in a dimension is called the extent of the array in that dimension. The shape of an array is determined from the rank and the extents; to be precise, the shape is a vector where each element of the vector is the extent in the corresponding dimension. The size of an array is the product of the extents; that is, it is the total number of elements in the array.

Example 1: Consider the following statement:

REAL X(0:9, 2)

The rank of X is 2 because X has two dimensions. The extent of the first dimension is 10; the extent of the second dimension is 2. The shape of X is 10 by 2, that is, a vector of two values, (10,2). The size is 20, the product of the extents.

An object can be given the DIMENSION attribute in a type declaration or in one of several other specification statements.

Example 2: Consider the following statements show some ways of declaring that A has rank 3 and shape (10, 15, 3):

DIMENSION A(10, 15, 3)
REAL, DIMENSION(10, 15, 3) :: A
REAL A(10, 15, 3)
COMMON A(10, 15, 3)
TARGET A(10, 15, 3)

Arrays of nonzero size have a lower and upper bound for each dimension. The lower bound is the smallest subscript value for a dimension; the upper bound is the largest subscript value for that dimension. The default lower bound is 1 if the lower bound is omitted in the declaration. Array bounds can be positive, zero, or negative.

Example 3: Consider the following statement:

REAL Z(-3:10, 12)

The first dimension of Z ranges from -3 to 10, that is, -3, -2, -1, 0, 1, 2, . . ., 9, 10. The lower bound is -3; the upper bound is 10. In the second dimension, the lower bound is 1; the upper bound is 12.

The bounds for array expressions are described in “The Extents of an Expression” in Chapter 7.

Whole Arrays

Some arrays are named. The name is either an array variable name or the name of a constant. If the array name appears without a subscript list or section subscript list, all of the elements of the array are referenced and the reference is considered to be a whole array reference.

Array Elements

An array element is one of the scalar elements that make up an array. A subscript list is used to indicate which element is referenced. Assume that A is declared to be a one-dimensional array, as follows:

REAL, DIMENSION(10) :: A

A(1) refers to the first element, A(2) to the second, and so on. The number in the parentheses is the subscript that indicates which scalar element is referenced. Assume that B is declared to be a seven-dimensional array, as follows:

REAL B(5, 5, 5, 5, 4, 7, 5)

B(2,3,5,1,3,7,2) refers to one scalar element of B, indexed by a subscript in each dimension. The set of numbers that indicate the position along each dimension in turn (in this case, 2,3,5,1,3,7,2) is called a subscript list.

Array Sections

Sometimes only a portion of an array is needed for a calculation. It is possible to refer to a selected portion of an array as an array; this portion is called an array section. A parent array is the whole array from which the portion that forms the array section is selected.

An array section is specified by an array variable name and a section subscript list that consists of subscripts, triplet subscripts, or vector subscripts. At least one subscript must be a triplet or vector subscript; otherwise, the reference indicates an array element, not an array section. The following example uses a section subscript to create an array section:

REAL A(10)
   . . .
A(2:5) = 1.0

The parent array A has 10 elements. The array section consists of the elements A(2), A(3), A(4), and A(5) of the parent array. The section A(2:5) is an array itself and the value 1.0 is assigned to all four of its elements.

Format of Array Elements and Array Sections

The format of an array element is a data reference, which is defined as follows:

 

array_element

is

data_ref

For a data reference to be classified as an array section, exactly one part reference must have nonzero rank, and either the final part reference must have a section subscript list with nonzero rank or another part reference must have nonzero rank.

The format of an array section is a data reference followed by an optional substring range enclosed in parentheses. This is defined as follows:

 

array_section

is

data_ref[ (substring_range) ]

The format of a substring range is found in “Substrings”.

A part name in a data reference can be followed by an optional section subscript list, as follows:

 

subscript

is

scalar_int_exp

 

section_subscript

is

subscript

 

 

or

subscript_triplet

 

 

or

vector_subscript

 

subscript_triplet

is

[subscript] : [subscript][ : stride]

 

stride

is

scalar_int_expr

 

vector_subscript

is

int_expr

Each subscript and stride must be a scalar_int_expr. A vector_subscript must be an integer array expression of rank one.

For a data reference to be classified as an array element, every part reference must have rank zero and the last part reference must contain a subscript list.

In an array section that is a data reference followed by a substring range, the rightmost part name must be of type character.

In an array section of an assumed-size array, the second subscript must not be omitted from a subscript triplet in the last dimension.

A section subscript must be present for each dimension of an array. If any section subscript is simply a subscript, the section will have a lesser rank than its parent.

If any part of a reference is an array section, the reference is considered to be an array section reference. In a data reference, there may be at most one part with rank greater than zero.

Examples of array elements and array sections are as follows:

ARRAY_A(1,2)        ! array element
ARRAY_A(1:N:2,M)    ! rank-one array section
ARRAY_B(:,:,:)(2:3)  ! array. elements are substrings of
                     ! of length 2
SCALAR_A%ARRAY_C(L)                    ! array element
SCALAR_A%ARRAY_C(1:L)                  ! array section
SCALAR_B%ARRAY_D(1:N)%SCALAR_C         ! array section
ARRAY_E(1:N:2)%ARRAY_F(I,J)%STRING(K)(:) ! array section

In the last example above, each component of the type definition is an array and the object ARRAY_E is an array. The reference is valid because each component in the reference is scalar. The substring range is not needed because it specifies the entire string; however, it serves as a reminder that the last component is of type character.

The following examples demonstrate the allowable combinations of scalar and array parents with scalar and array components.

TYPE REPAIR_BILL
   REAL PARTS(20)
   REAL LABOR
END TYPE REPAIR_BILL

TYPE(REPAIR_BILL) FIRST
TYPE(REPAIR_BILL) FOR_1990(6)Scalar parent: 1. FIRST % LABOR          ! structure component
 2. FIRST % PARTS(I)       ! array element
 3. FIRST % PARTS          ! component (array-valued)
 4. FIRST % PARTS(I:J)     ! array section

 5. FOR_1990(K) % LABOR    ! structure component
 6. FOR_1990(K) % PARTS(I) ! array element
 7. FOR_1990(K) % PARTS    ! component (array-valued)
 8. FOR_1990(K) % PARTS(I:J) ! array sectionArray parent: 9. FOR_1990 % LABOR       ! component and array section
10. FOR_1990 % PARTS(I)   ! array section
11. FOR_1990 % PARTS      ! ILLEGAL
12. FOR_1990 % PARTS(I:J) ! ILLEGAL

13. FOR_1990(K:L) % LABOR ! component and array section
14. FOR_1990(K:L) % PARTS(I) ! array section
15. FOR_1990(K:L) % PARTS ! ILLEGAL
16. FOR_1990(K:L) % PARTS(I:J) ! ILLEGALText goes here

References 11, 12, 15, and 16 are illegal because only one component may be of rank greater than zero. References 3 and 7 are compact (contiguous) array objects and are classified as array-valued structure components. References 9, 10, 13, and 14 are noncontiguous array objects and are classified as sections. These distinctions are important when such objects are actual arguments in procedure references.

Subscripts

In an array element reference, each subscript must be within the bounds for that dimension. A subscript can appear in an array section reference. Whenever this occurs, it decreases the rank of the section by one less than the rank of the parent array. A subscript used in this way must be within the bounds for the dimension. The CF90 and MIPSpro 7 Fortran 90 compilers allow overindexing, which may produce incorrect results because of optimization. For information on overindexing and optimization, see the Fortran Language Reference Manual, Volume 3.


Note: The Fortran standard does not address overindexing.


Subscript Triplets

The first subscript in a subscript triplet is the lower bound; the second is the upper bound. If the lower bound is omitted, the declared lower bound is used. If the upper bound is omitted, the declared upper bound is used. The stride is the increment between successive subscripts in the sequence. If it is omitted, it is assumed to be 1. The stride must not be 0. If the subscripts and stride are omitted and only the colon (:) appears, the entire declared range for the dimension is used.

When the stride is positive, an increasing sequence of integer values is specified from the first subscript in increments of the stride, up to the last value that is not greater than the second subscript. The sequence is empty if the first subscript is greater than the second. If any subscript sequence is empty, the array section is a zero-sized array, because the size of the array is the product of its extents. For example, given the array declared A(5,4,3) and the section A(3:5,2,1:2), the array section is of rank 2 with shape (3,2) and size 6. The elements are as follows:

A(3,2,1)     A(3,2,2)
A(4,2,1)     A(4,2,2)
A(5,2,1)     A(5,2,2)

When the stride is negative, a decreasing sequence of integer values is specified from the first subscript, in increments of the stride, down to the last value that is not less than the second subscript. The sequence is empty if the second subscript is greater than the first, and the array section is a zero-sized array. For example, given the array declared B(10) and the section B(9:4:-2), the array section is of rank 1 with shape (3) and size 3. The elements are as follows:

B(9) B(7) B(5) 

However, array section B(9:4) is a zero-sized array.

A subscript in a subscript triplet is not required to be within the declared bounds for the dimension as long as all subscript values selected by the triplet are within the declared bounds. For example, given an array declared B(10), section B(3:11:7) is permitted. It has rank 1 with shape (2) and size 2. The elements are as follows:

B(3) B(10)

Vector Subscripts

While subscript triplets specify values in increasing or decreasing order with a specified stride to form a regular pattern, vector subscripts specify values in arbitrary order. The values must be within the declared bounds for the dimension. A vector subscript is a rank-one array of integer values used as a section subscript to select elements from a parent array.

INTEGER J(3)
REAL A(30)
   . . .
J = (/ 8, 4, 7 /)
A(J) = 1.0

The last assignment statement assigns the value 1.0 to A(4), A(7), and A(8). The section A(J) is a rank-one array with shape (3) and size 3.

If J were assigned (/ 4, 7, 4 /) instead, the element A(4) would be accessed in two ways: as A(J(1)) and as A(J(3)). Such an array section is called a many-to-one array section. A many-to-one section must not appear on the left of the equal sign in an assignment statement or as an input item in a READ statement. The reason is that the result will depend on the order of evaluation of the subscripts, which is not specified by the language. The results would not be predictable and the program containing such a statement would not be portable.

Array sections with vector subscripts are array expressions, so there are places, such as the following, where array sections with vector subscripts must not appear:

  • As internal files

  • As pointer targets

  • As actual arguments for INTENT(OUT) or INTENT(INOUT) dummy arguments

Using Array Elements and Array Sections

Subscripts, subscript triplets, and vector subscripts can be mixed in a single section subscript list used to specify an array section. A triplet section can specify an empty sequence (for example 1:0), in which case the resulting section is a zero-sized array.

Example 1: Assume that B is declared as follows:

REAL B(10, 10, 5)

Section B(1:4:3, 6:8:2, 3) consists of the following four elements:

B(1,6,3)     B(1,8,3)
B(4,6,3)     B(4,8,3)

The stride along the first dimension is 3, resulting in a subscript-value list of 1 and 4. The stride along the second dimension is 2, resulting in a subscript-value list of 6 and 8. In the third position there is a subscript that reduces the rank of the section by 1. The section has shape (2, 2) and size 4.

Example 2: Assume IV is declared as follows:

INTEGER, DIMENSION(3) :: IV = (/ 4, 5, 4 /)

Then the section B(8:9, 5, IV) is a 2 x 3 array consisting of the following six elements:

B(8,5,4)     B(8,5,5)     B(8,5,4)
B(9,5,4)     B(9,5,5)     B(9,5,4)

B(8:9, 5:4, IV) is a zero-sized array of rank 3.

Array Element Order

When whole arrays are used as operands in an executable statement, the indicated operation is performed element-by-element, but no order is implied for these elemental operations. They can be executed in any order or simultaneously. Although there is no order of evaluation when whole array operations are performed, there is an ordering of the elements in an array itself. An ordering is required for the input and output of arrays and for certain intrinsic functions such as MAXLOC(3i). The elements of an array form a sequence whose ordering is called array element order. This is the sequence that occurs when the subscripts along the first dimension vary most rapidly, and the subscripts along the last dimension vary most slowly. Thus, for an array declared as REAL A(3, 2), the elements in array element order are: A(1, 1), A(2, 1), A(3, 1), A(1, 2), A(2, 2), A(3, 2).

The position of an array element in this sequence is its subscript order value. Element A(1, 1) has a subscript order value of 1. Element A(1, 2) has a subscript order value of 4. Figure 6-1, shows how to compute the subscript order value for any element in arrays of rank 1 through 7.

Figure 6-1. Computation of subscript order value

Computation of subscript order value

The subscript order of the elements of an array section is that of the array object that the section represents. That is, given the array A(10) and the section A(2:9:2) consisting of the elements A(2), A(4), A(6), and A(8), the subscript order value of A(2) in the array section A(2:9:2) is 1; the subscript order value of A(4) in the section is 2 and A(8) is 4.

Pointers and Allocatable Arrays

Fortran provides several dynamic data objects. Automatic objects (arrays and character strings) are discussed in “Automatic Data Objects” in Chapter 5. In addition, there are two data attributes that can be used to specify dynamic data objects: ALLOCATABLE and POINTER. Arrays of any type can have the ALLOCATABLE attribute; scalars or arrays of any type can have the POINTER attribute. Chapter 5, “Declarations”, described how such objects are declared. This section describes how space is created for these objects with the ALLOCATE statement, how it can be released with the DEALLOCATE statement, and how pointers can be disassociated from any target with the NULLIFY statement. The association status of a pointer can be defined or undefined; initially (when a pointer is declared), it is undefined. If it is defined, the pointer can be associated with a target or disassociated from any target. The target is referenced by the name of the pointer and is like any other variable in that it is defined when it acquires a value. Figure 6-2 shows the various states that a pointer may assume.

Figure 6-2. States in the lifetime of a pointer

States in the lifetime of a pointer

“Pointer Assignment” in Chapter 7, describes how pointers can be associated with existing space and how dynamic objects can acquire values.

ALLOCATE Statement

The ALLOCATE statement creates space for the following:

  • Arrays with the ALLOCATABLE attribute

  • Variables with the POINTER attribute

The ALLOCATE statement is defined as follows:

 

allocate_stmt

is

ALLOCATE (allocation_list[, STAT = stat_variable])

 

stat_variable

is

scalar_int_variable

 

allocation

is

allocate_object[ (allocate_shape_spec_list) ]

 

allocate_object

is

variable_name

 

 

or

structure_component

 

allocate_shape_spec

is

[allocate_lower_bound : ]allocate_upper_bound

 

allocate_lower_bound

is

scalar_int_expr

 

allocate_upper_bound

is

scalar_int_expr

The stat_variable, allocate_lower_bound, and allocate_upper_bound must each be scalar integer expressions.

Each allocate_object must be a pointer or an allocatable array.

An attempt to allocate space for an allocatable array that is currently allocated results in an error condition.

An allocate_object or a subobject of an allocate_object cannot appear in a bound in the same allocate statement.

If a STAT= variable appears, it must not be allocated in the same ALLOCATE statement. A STAT= variable cannot depend on the value, bounds, allocation status, or association status of any allocate_object or subobject of an allocate_object allocated in the same statement. It is set to zero if the allocation is successful and is set to a positive value if there is an error condition; when an error is detected, subsequent items in the allocation_list are not allocated. If there is no STAT= variable, the program terminates when an error condition occurs.

You can obtain an online explanation of an error identified by the STAT= return value. To do this, join the returned value with its group name, shown in the following list, and use the resulting string as an argument to the explain(1) command. For example:

explain lib-5000
explain 90476

Table 6-1. Message number identifiers

Message number

Group name

Source of message

1 through 899

sys

Operating system

1000 through 1999

lib

Fortran library (UNICOS and UNICOS/mk systems)

4000 through 4999

lib

Fortran library (IRIX systems)

5000 through 5999

lib

Flexible File I/O (FFIO) library

90000 through 90500

None

Tape system

An argument to an inquiry function in an ALLOCATE statement must not appear as an allocate object in that statement. For example, the use of the intrinsic inquiry function SIZE in the following code is not permitted.

REAL, ALLOCATABLE :: A(:), B(:)
ALLOCATE (A(10), B(SIZE(A)))

The number of allocate shape specifications must agree with the rank of the array.

If the lower bound is omitted, the default is 1. If the upper bound is less than the lower bound, the extent in that dimension is 0 and the array has zero size.

An allocate object can be of type character and it can have a length of 0, in which case no memory is allocated.

The values of the bounds expressions at the time an array is allocated determine the shape of the array. If an entity in a bounds expression is subsequently redefined, the shape of the allocated array is not changed.

Allocation of Allocatable Arrays

You must declare the rank of an allocatable array, but the bounds, extents, shape, and size are determined when the array is allocated. After allocation the array can be defined and redefined. The array then is said to be currently allocated. It is an error to allocate an allocatable array that is already allocated. The intrinsic function ALLOCATED(3i) can be used to query the allocation status of an allocatable array if the allocation status is defined, for example:

REAL, ALLOCATABLE :: X(:, :, :)
   . . .
IF (.NOT. ALLOCATED(X)) ALLOCATE (X(-6:2, 10, 3))

X is not available for use in the program until it has been allocated space by an ALLOCATE statement. X must be declared with a deferred-shape array specification and the ALLOCATABLE attribute.

Allocation of Pointers

When an object with the POINTER attribute is allocated, space is created, and the pointer is associated with that space, which becomes the pointer target. A reference to the pointer name can be used to define or access its target. The target can be an array or a scalar. Additional pointers can become associated with the same target by pointer assignment (described in “Pointer Assignment” in Chapter 7). A pointer target can be an array with the ALLOCATABLE attribute if the array also has the TARGET attribute. Allocation of a pointer creates an object that implicitly has the TARGET attribute.

It is not an error to allocate a pointer that is currently associated with a target. In this case, a new pointer target is created and the previous association of the pointer is lost. If there was no other way to access the previous target, it becomes inaccessible.

The ASSOCIATED(3i) intrinsic function can be used to query the association status of a pointer if the association status of the pointer is defined. The ASSOCIATED(3i) intrinsic function also can be used to inquire whether a pointer is associated with a target or whether two pointers are associated with the same target.

Pointers can be used in many ways; an important usage is creating linked lists. For example:

TYPE NODE
   INTEGER :: VALUE
   TYPE(NODE), POINTER :: NEXT
END TYPE NODE

TYPE(NODE), POINTER :: LIST
    . . .
ALLOCATE(LIST)
LIST%VALUE = 17
ALLOCATE(LIST%NEXT)

The first two executable statements create a node pointed to by LIST and put the value 17 in the VALUE component of the node. The third statement creates a second node pointed to by the NEXT component of the first node.

NULLIFY Statement

The NULLIFY statement causes a pointer to be disassociated from any target. Pointers have an initial association status that is undefined. To initialize a pointer to point to no target, it is necessary to execute a NULLIFY statement for the pointer.

The NULLIFY statement is defined as follows:

 

nullify_stmt

is

NULLIFY (pointer_object_list)

 

pointer_object

is

variable_name

 

 

or

structure_component

Each pointer_object must have the POINTER attribute.

A pointer_object cannot depend on the value, bounds, or association status of another pointer_object or subobject of another pointer_object in the same NULLIFY statement.

DEALLOCATE Statement

The DEALLOCATE statement releases the space allocated for an allocatable array or a pointer target and nullifies the pointer. After an allocatable array or pointer has been deallocated, it cannot be accessed or defined until it is allocated again or, in the case of a pointer, assigned to an existing target.

In some cases, the execution of a RETURN statement in a subprogram may cause the association status of a pointer to become undefined. This can be avoided if the pointer is given the SAVE attribute or if it is declared in a subprogram that remains active. (The main program is always active. Variables declared in modules accessed by the main program and named common blocks specified in the main program do not need to be given the SAVE attribute; these entities have the attribute automatically. If the main program calls subroutine A and subroutine A calls function B, then the main program, subroutine A, and function B are active until a return from function B is executed, at which time only the main program and subroutine A are active. If a recursive subprogram becomes active, it remains active until the return from its first invocation is executed.)

The DEALLOCATE statement is defined as follows:

 

deallocate_stmt

is

DEALLOCATE (allocate_object_list[, STAT = stat_variable])

The stat_variable must be a scalar integer variable.

Each allocate_object must be a pointer or an allocatable array.

An allocate_object must not depend on the value, bounds, allocation status, or association status of another allocate_object or subobject of another allocate_object in the same DEALLOCATE statement, nor can it depend on the value of the stat_variable in the same DEALLOCATE statement.

If there is a STAT= variable and it is a pointer, it must not be deallocated in the same DEALLOCATE statement, nor can it depend on the value, bounds, allocation status, or association status of any allocate_object or subobject of an allocate_object in the same DEALLOCATE statement. The stat_variable is set to zero if the deallocation is successful and is set to a positive value if there is an error condition. If STAT=stat_variable is not specified, the program terminates when an error condition occurs.

You can obtain an online explanation of an error identified by the STAT= return value. To do this, join the returned value with its group name, shown in the following list, and use the resulting string as an argument to the explain(1) command. For example:

explain lib-5000
explain 90476

Table 6-2. Message number identifiers

Message number

Group name

Source of message

1 through 899

sys

Operating system

1000 through 1999

lib

Fortran library (UNICOS and UNICOS/mk systems)

4000 through 4999

lib

Fortran library (IRIX systems)

5000 through 5999

lib

Flexible File I/O (FFIO) library

90000 through 90500

None

Tape system


Deallocation of Allocatable Arrays

To be deallocated, an allocatable array must be currently allocated; otherwise, an error condition will occur. You can use the inquiry intrinsic function ALLOCATED(3i) to determine if an array is currently allocated.

An allocatable array can have the TARGET attribute. If such an array is deallocated, the association status of any pointer associated with the array will become undefined. Such an array must be deallocated by the appearance of its name in a DEALLOCATE statement. It must not be deallocated by the appearance of the pointer name in a DEALLOCATE statement.

When a RETURN or END statement is executed in a subprogram, local allocatable arrays are deallocated unless any of the following conditions exist:

  • The array has the SAVE attribute

  • The array is specified in a module that is accessed by an active subprogram

  • The array is accessed by host association

The following is an example of the allocation and deallocation of an allocatable array:

REAL, ALLOCATABLE :: X(:, :)
   . . .
ALLOCATE (X(10, 2), STAT = IERR)
IF (IERR .GT. 0) CALL HANDLER
X = 0.0
   . . .
DEALLOCATE (X)
   . . .
ALLOCATE (X(-10:10, 5), STAT = JERR)

X is declared to be a deferred-shape, two-dimensional, real array with the ALLOCATABLE attribute. Space is allocated for it and it is given bounds, extents, shape, and size and then initialized to have zero values in all elements. Later X is deallocated, and still later, it is again allocated with different bounds, extents, shape, and size, but its rank remains as declared.

Deallocation of Pointers

Only a pointer with defined association status can be deallocated. Deallocating a pointer with an undefined association status or a pointer associated with a target that was not created by allocation causes an error condition in the DEALLOCATE statement. A pointer associated with an allocatable array must not be deallocated. (Of course, the array itself can be deallocated.)

It is possible (by pointer assignment) to associate a pointer with a portion of an object such as an array section, an array element, or a substring. A pointer associated with only a portion of an object cannot be deallocated. If more than one pointer is associated with an object, deallocating one of the pointers causes the association status of the others to become undefined. Such pointers must not be arguments to the ASSOCIATED(3i) inquiry function.

When a RETURN or END statement is executed in a procedure, the association status of a pointer declared or accessed in the procedure becomes undefined unless one of the following conditions is true:

  • The pointer has the SAVE attribute

  • The pointer is specified in a module that is accessed by an active subprogram

  • The pointer is accessed by host association

  • The pointer is in blank common

  • The pointer is in a named common block that is specified in an active subprogram or has the SAVE attribute

  • The pointer is the return value of a function declared to have the POINTER attribute

If the association status of a pointer becomes undefined, the pointer can no longer be referenced, defined, or deallocated. It can be allocated, nullified, or pointer-assigned to a new target.

The following is an example of the allocation and deallocation of a pointer:

REAL, POINTER :: X(:, :)
   . . .
ALLOCATE (X (10, 2), STAT = IERR)
IF (IERR .GT. 0) CALL HANDLER
X = 0.0
   . . .
DEALLOCATE (X)
   . . .
ALLOCATE (X(-10:10, 5), STAT = JERR)

X is declared to be a deferred-shape, two-dimensional, real array with the POINTER attribute. Space is allocated for it and it is given bounds, extents, shape, and size and then initialized to have zero values in all elements. Later X is deallocated, and still later, it is again allocated with different bounds, extents, shape, and size. This example is quite similar to the previous example for allocatable arrays, except that, in the case of pointers, it is not necessary to deallocate X before allocating it again.