Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
HP Fortran Compiler for HP-UX: HP Fortran Programmer's Reference > Chapter 5 Data types and data objects

Derived types

» 

Technical documentation

Complete book in PDF
» Feedback
Content starts here

 » Table of Contents

 » Glossary

 » Index

Derived types are user-defined types that are constructed from entities of intrinsic data types (see “Intrinsic data types”) or entities of previously defined derived types. For example, the following is a definition of a derived type for manipulating coordinates consisting of two real numbers:

TYPE coord
REAL :: x,y
END TYPE coord

x and y are the components of the derived type coord.

The next statement declares two variables (a and b) of the derived type coord:

TYPE(coord) :: a, b

The next statement copies the values of a to b, as in any assignment statement:

a = b

The components of a and b are referenced as a%x, a%y, b%x, and b%y. By using the defined operation facility of Fortran 90, it is possible to extend the standard operators to work with derived types. For example, if the + and = operators were re-defined to operate on derived type operands, the following statement

a = a + b

would be equivalent to

a%x = a%x + b%x;  a%y = a%y + b%y

The following sections describe:

  • The syntax of defining a derived type

  • Sequence types

  • Structure constructors

  • Referencing a structure component

  • Alignment of derived type objects

The last section provides an example program that illustrates different features of derived types.

Defining a derived type

The format for defining a derived type is:

TYPE [[, access-spec] ::] type-name
 [private-sequence-statement] ...
 comp-definition-statement
 [comp-definition-statement] ...
END TYPE [type-name]
access-spec

is one of:

  • PRIVATE

  • PUBLIC

access-spec is allowed only if the definition appears within a module. For more information about modules, see “Modules”. The PRIVATE and PUBLIC attributes are described in Chapter 10.

type-name

is the name of the type being defined. type-name must not conflict with the intrinsic type names.

private-sequence-statement

is a PRIVATE or SEQUENCE statement. The PRIVATE statement is allowed only if the definition appears within a module. For more information about the SEQUENCE statement, see “Sequence derived type”. Both statements are fully described in Chapter 10.

comp-definition-statement

takes the form:

type-spec [[comp-attr-list]::]comp-decl

Notice that the syntax does not allow for initialization.

comp-attr-list

can only contain the DIMENSION and POINTER attributes. A component array without the POINTER attribute must have an explicit-shape specification with constant bounds. If a component is of the same derived type as the type being defined then the component must have the POINTER attribute. Both attributes are fully described in Chapter 10.

comp-declaration

takes the form:

comp-name [(array-spec)][*char-len]

where array-spec is an array specification, as described in “Array declarations”; and char-len is used when comp-name is of type character to specify its length.

Sequence derived type

As shown in “Defining a derived type”, the SEQUENCE statement may appear in the definition of a derived type. When storage for a variable of derived type is allocated, the presence of the SEQUENCE statement in the definition of the derived type causes the compiler to arrange all components in a storage sequence that is the same as the order in which they are defined. Such a derived type is called a sequence derived type.

A sequence derived type may appear in a common block or in an equivalence set. The Standard makes requirements about the type—numeric or character—of the components in a sequence type. As an extension, HP Fortran makes no restrictions on the types of the components other than that the definition of the derived type must include the SEQUENCE statement.

Structure component

A component of a derived-type object may be referenced and used like any other variable—in an expression, on the lefthand side of an assignment statement, or as procedure argument. It may be a scalar, an array, or itself a derived-type object. The component name has the same scope as the derived-type object in which it is declared.

To reference a structure component, use the form:

parent-name[%comp-name]...%comp-name
parent-name

is a derived type. This part of a structure component reference is the parent and is joined to comp-name by the component selector operator (%). The comp-name component to which the parent is joined on its immediate right must be a component of parent-name. If parent-name has the INTENT, TARGET, or PARAMETER attribute, then the structure component being referenced—the rightmost comp-name—also has that attribute.

comp-name

is the name of a component. If more than one comp-name appears in a structure component reference, the reference is to the rightmost comp-name. If more than one comp-name appears in the reference, each one (except the rightmost) must be a derived-type object, and the comp-name to its immediate right must be one of its declared components.

If parent-name and comp-name are arrays, each can be followed by a section-subscript-list enclosed in parentheses. See “Array sections” for information about the syntax of section-subscript-list. The Standard imposes certain restrictions on structure component references that are array-valued, as described in “Array-valued structure component references”.

If the definition of a derived type contains a component that is of the same derived type, the component must have the POINTER attribute. The following example defines the derived type node, which includes a component (next) of the same derived type:

TYPE node  ! for use in a singly linked list
INTEGER :: value
TYPE(node), POINTER :: next ! must have the POINTER attribute
END TYPE node

Declaring a derived type-object

To declare an object of derived type, use the TYPE statement, as follows:

TYPE (type-name) [[, attrib-list] :: ] entity-list

where type-name, attrib-list, and entity-list all have the same meaning as in a type declaration statement that is used to declare an object of an intrinsic type; see “Type declaration for intrinsic types”.

Structure constructor

A structure constructor constructs a scalar value of derived type. The value is constructed of a sequence of values for each component of the type. The syntax of a structure constructor is:

type-name ( expression-list )
type-name

is the name of the derived type. The name must have been previously defined.

expression-list

is a comma-separated list of expressions that must agree in number, order, and rank with the components in type-name. For information about expressions, see “Expressions” and “Special forms of expression”.

The following restrictions apply to the use of the structure constructor:

  • If a component is of derived type, an embedded structure constructor must be used to specify a value for the derived-type component.

  • If a component is an array, an array constructor must appear in expression-list that satisfies the array. For more information about array constructors, see “Array constructors”.

  • If a component is a pointer, the corresponding expression in expression-list must evaluate to an allowable target.

Alignment of derived-type objects

Derived type objects have the same alignment as the component that has the most restrictive alignment requirement. (This rule also applies to records.) To ensure natural alignment, the compiler may add padding to each element in an array of derived type.

The following illustrates the alignment of an array of derived type. The definition of the derived type includes the SEQUENCE statement to ensure the order in which components are laid out in memory is the same as in the definition. The SEQUENCE statement has no effect on alignment:

! definition of a derived type
TYPE t
SEQUENCE
CHARACTER(LEN=7) :: c
INTEGER(2) :: i2
REAL(8) :: r8
REAL(4) :: r4
END TYPE t

! declaration of an array variable of derived type
TYPE (t), DIMENSION(5) :: ta

Each element of t is allocated storage as shown in Table 5-4 “Example of structure storage”. The first component of t starts at an address that is a multiple of 8. The four trailing padding bytes are necessary to preserve the alignment of r8 in each element of the array.

Table 5-4 Example of structure storage

Component

Byte offset

Length

c

0

7

i2

8

2

r8

16

8

r4

24

4

padding

28

4

 

A derived-type example

The example below, traffic.f90, illustrates how to define a derived type, declare a variable of the type, specify a value for the variable using the structure constructor, pass the variable as an argument to another procedure, and reference a structure component. The derived type is defined in a module so that it can be made accessible by use association.

For more information about modules and the USE statement, see “Modules”. The MODULE and USE statements are also described in Chapter 10.

Example 5-3 traffic.f90

PROGRAM traffic
! Illustrates derived types: defines a derived type, declares an
! to array variable of derived type, uses a structure constructor
! assign to its components, and passes a component which is
! itself another derived type to a subprogram.

! Make the definition of the derived type called hours accessible
! to this program unit
USE hours_def

LOGICAL :: busy
INTEGER :: choice

! Define another derived type that uses hours as a component
TYPE hiway
INTEGER :: rte_num
TYPE(hours) :: busy_hours
END TYPE hiway

! Declare an array of derived-type structures.
TYPE(hiway), DIMENSION(3) :: route

! Use the structure constructor to specify values for each
! element of route
route(1) = hiway(128, hours(.TRUE., .FALSE.))
route(2) = hiway(93, hours(.FALSE., .TRUE.))
route(3) = hiway(97, hours(.FALSE., .FALSE.))

PRINT *, 'What road do you want to travel?'PRINT *, '1. Rte. 128'
PRINT *, '2. Rte. 93'
PRINT *, '3. Rte 97'
READ *, choice

! Pass the busy_hours component of the selected route to
! the function busy.
IF (busy(route(choice)%busy_hours)) THEN
PRINT *,’Heavy commute on rte.’, route(choice)%rte_num
ELSE
PRINT *,’Easy commute on rte.’, route(choice)%rte_num
END IF

END PROGRAM traffic

LOGICAL FUNCTION busy(when)
! This function accepts a derived-type argument whose definition
! is defined in the module hours_def, made accessible here by
! use association. It returns .TRUE. or .FALSE., depending on
! on the value of the user-selected component of the argument.

! Make the definition of hours accessible to this function.
USE hours_def

TYPE(hours) :: when

INTEGER :: choice

PRINT *, 'When do you want to commute:'
PRINT *, '1. Morning'
PRINT *, '2. Evening'
READ *, choice

! Find out if the route is busy at that time of day.
IF (choice .EQ. 1) THEN
busy = when%am
ELSE
busy = when%pm
END IF

END FUNCTION busy

MODULE hours_def
! Define a derived type, which will be passed as an argument.
TYPE hours
LOGICAL :: am
LOGICAL :: pm
END TYPE hours
END MODULE hours_def

Here are the command lines to compile and execute the program, along with the output from a sample run:

$ f90 traffic.f90
$ a.out
What road do you want to travel?
1. Rte. 128
2. Rte. 93
3. Rte 97
1
When do you want to commute:
1. Morning
2. Evening
1
Heavy commute on rte. 128
Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© Hewlett-Packard Development Company, L.P.