Initialisation

The value of every variable and array element is undefined at the start of program execution unless it has been initialised in a DATA statement. Undefined values may be used in executable statements only in ways which cause them to become defined. There are a number of ways of assigning a value to a variable or array element, including:

Using undefined variables in any other way can cause obscure errors which are fiendishly difficult to track down. Make sure your variables and arrays are properly initialised before you use them.

Assignment Operator

The equals sign = acts as an assignment operator in FORTRAN 77.

An arithmetic assignment statement has the form

symbolic name = arithmetic expression

where the symbolic name represents a variable or array element of type COMPLEX, DOUBLE PRECISION, INTEGER or REAL. If the arithmetic expression on the right side of the = operator has a different type from the symbolic name on the left, type conversion is automatically applied to the value of the arithmetic expression before it is applied to the variable or array element.

Example

Consider this program fragment where an array and a number of variables are declared and then initialised.

      COMPLEX          X
      DOUBLE PRECISION DUB
      INTEGER          K,L
      REAL             ARRAY(5),Y,Z
      Y   = 119.7
      Z   = -0.45E+01
      X   = (Y,Z)
      DUB = 3.21D+08
      K   = Y
      DO 10, L = 1,5
         ARRAY(L) = 2.0*Y + L*Z
   10 CONTINUE

In this example, the REAL variable Y is assigned the value 119.7 and the REAL variable Z is assigned the value -4.5.

The COMPLEX variable X holds the value which can be written mathematically as 119.7 - 4.5i.

The variable DUB is given the value 3.21 × 108 using double precision rather than single precision.

In the statement K = Y, automatic type conversion occurs since K is type INTEGER and Y is type REAL. However, the value assigned to K is 119 and not 120. The REAL value is truncated, not rounded.

Finally, a DO loop is used to initialise the REAL array:

An character assignment statement has the form

symbolic name = character expression

where the symbolic name represents a variable, array element or substring of type CHARACTER.

Example

      CHARACTER BYE*20,GREET*5,HELLO*11
      HELLO       = 'Hello world'
      HELLO(7:11) = 'Earth'

In the first assignment statement, the string Hello world is assigned to the variable HELLO and is stored as Helloworld where is a blank or space. The second assignment statement assigns the string Earth to the substring HELLO(7:11) which means the variable HELLO now contains HelloEarth. The previously defined values in positions 1 through 6 are unaffected. (If HELLO had not been previously defined, then those positions would still be undefined.)

Now consider what happens if the expression on the right is longer than the variable on the left:

      GREET = HELLO

In this statement, a character expression of length 11 is assigned to a variable of length 5. When this occurs, the characters after position 5 are lost and the variable GREET contains Hello, the first 5 characters of HELLO.

Finally, examine the case where the expression on the right is shorter than the variable on the left:

      BYE = 'Farewell'

When this happens, blanks are appended (added to the right side). The variable BYE is stored as Farewell.

An logical assignment statement has the form

symbolic name = logical expression

where the symbolic name represents a variable or array element of type LOGICAL.

Example

      CHARACTER*1 ANS
      LOGICAL     DEBUG
      WRITE(*,*)'Do you wish to turn debugging on?  Y/N'
      READ(*,10)ANS
   10 FORMAT(A)
      DEBUG = ANS .EQ. 'Y' .OR. ANS .EQ. 'y'

The logical expression ANS .EQ. 'Y' .OR. ANS .EQ. 'y' evaluates to .TRUE. only if ANS contains either Y or y. Once the expression is evaluated, the value assigned to the LOGICAL variable DEBUG

= Is Not 'Equals'

It is important to realise that the assignment operator = is not an 'equals sign' in the mathematical sense. In FORTRAN 77, the assignment operator = always assigns the value on the right side of the operator to the symbolic name on the left side of the operator. Thus, X = -13 is a valid arithmetic assignment statement but -13 = X is not, even though the mathematical statements x = -13 and -13 = x are equivalent.

PARAMETER Statement

A variable is simply a named memory location of a fixed type. The value of a variable can be changed during the execution of the program. A named constant, on the other hand, is fixed at compile time and cannot be changed. The PARAMETER statement is used to assign a constant value to a symbolic name.

PARAMETER(cname1 = value1, cname2 = value2, …, cnamen = valuen)

Although the value of a FORTRAN 77 constant cannot be changed elsewhere in the program, it can be used in other PARAMETER statements as well as in type declarations, DATA statements and in calculations.

Example

      DOUBLE PRECISION DEG,PI,RAD,TWOPI
      PARAMETER(PI=3.141592653589793D0,TWOPI=2D0*PI)
…
      RAD = DEG*PI/180D0

The value of the DOUBLE PRECISION constant PI is assigned in the PARAMETER statement. The value of another DOUBLE PRECISION constant, TWOPI, is also assigned in the same PARAMETER statement. This is done simply by multiplying the already-defined constant PI by 2D0. Later in the program, the value of PI is used in an arithmetic expression.

Example

      INTEGER   COLS,ROWS
      PARAMETER(ROWS=12,COLS=10)
      REAL      MATRIX(ROWS,COLS),VECTOR(ROWS)

In this set of declarations, the constants COLS and ROWS are declared to be of type INTEGER before being given the values in the following PARAMETER statement. After the constants have been defined, they can be used in the array declarations on the next line. Using named constants as array bounds is a common application in FORTRAN 77.

CHARACTER constants are also possible. They can be declared in the following manner:

CHARACTER*(*) cname
PARAMETER(cname = 'string')

The length of the CHARACTER constant cname is automatically set to the length of the string in the PARAMETER statement. This only works with CHARACTER constants, not CHARACTER variables which must have the length explicitly declared. The CHARACTER*(*) statement must precede the PARAMETER statement.

Example

      CHARACTER*(*) ERRMSG
      PARAMETER(ERRMSG='Division by zero!')

In this example, the CHARACTER constant ERRMSG is 17 characters long and contains the string Division by zero!

LOGICAL constants can take the values .TRUE. or .FALSE.

Example

      LOGICAL DEBUG
      PARAMETER(DEBUG=.TRUE.)
…
      IF (DEBUG) WRITE(*,*)'Entering first DO loop'

The LOGICAL constant DEBUG is set to .TRUE. and is used in an IF statement later in the program.

DATA Statement

The DATA statement is also used to initialise variables and arrays. It takes the form

DATA var-list1 /value-list1/, var-list2 /value-list2/, …, var-listn /value-listn/

where var-list is a list of variable names, array names, substring names and implied DO lists, and value-list is a list of literal or named constants, optionally preceded by a repeat-count and an asterisk *. The repeat-count is either an unsigned integer value or a named constant.

The DATA statement must follow the type specification statements but can appear anywhere else in the program unit. By convention, they always appear directly after the specification statements and before the executable statements.

The important difference between the DATA and PARAMETER statements is that the DATA statement specifies an initial value for a variable or array element which may be subsequently changed during program execution. The value of a named constant defined by a PARAMETER statement may not be changed.

Example

      CHARACTER IFILE*20
      INTEGER   YEAR
      LOGICAL   DEBUG
      DATA      IFILE /'myinput.dat'/, YEAR /2013/, DEBUG /.FALSE./

In this example, the CHARACTER variable is initialised to the value myinput.dat where is a blank or space. YEAR takes the initial value 2013 and DEBUG is set to .FALSE.

An equivalent set of statements would be

      CHARACTER IFILE*20
      INTEGER   YEAR
      LOGICAL   DEBUG
      DATA      IFILE,YEAR,DEBUG /'myinput.dat',2013,.FALSE./

or even

      CHARACTER IFILE*20
      INTEGER   YEAR
      LOGICAL   DEBUG
      DATA      IFILE /'myinput.dat'/
      DATA      YEAR /2013/
      DATA      DEBUG /.FALSE./

although there is little to recommend this last version.

Initialising Arrays

Either an entire array or just certain specified elements can be initialised in a DATA statement. If the entire array is being initialised, then just the name of the array is used in the DATA statement but all of the elements must then be initialised.

Example

      LOGICAL OFFON(500)
      REAL    MASS(500)
      DATA    MASS /500*0.0/, OFFON /100*.TRUE.,400*.FALSE./

A repeat count of 500 is used to initialise all elements of the array MASS to 0.0. The first 100 elements of the array OFFON are initialised to .TRUE. and the remaining 400 elements are set to .FALSE..

It is common practice to use named constants as array bounds and it is permissible to use named constants (but not expressions involving named constants) in DATA statements.

      INTEGER   N1,N2,NTOTAL
      REAL      ZERO
      PARAMETER(N1=100, N2=400, NTOTAL=N1+N2, ZERO=0.0)
      LOGICAL   OFFON(NTOTAL)
      REAL      MASS(NTOTAL)
      DATA      MASS /NTOTAL*ZERO/, OFFON /N1*.TRUE.,N2*.FALSE./

This code accomplishes the same task as the previous snippet but uses named constants in the DATA statement.

If only a few elements of an array are to initialised, then each element must be listed separately.

Example

      INTEGER SMALL(10)
      DATA    SMALL(2),SMALL(7) /4,-14/, 

Only the second and seventh elements of the array SMALL are initialised. All of the rest of the array elements remain undefined.

Implied DO loop

An implied DO loop allows selective access to array elements and is used in I/O statements as well as DATA statements. The general form of the implied DO loop is

(data-listloop-control-variable = initial-valuefinal-valuestep-size)

The rules for the initial-value, final-value and step-size are exactly the same as for a DO loop. An implied DO loop may contain other implied DO loops nested within.

Example

      LOGICAL ODD(100)
      DATA    (ODD(I),I=1,99,2) /50*.TRUE./,
     $        (ODD(I),I=2,100,2) /50*.FALSE./

The first line of the DATA statement assigns the value .TRUE. to the array elements with odd-numbered indices whilst the continuation line of the statement initialises the even-numbered array elements with the value .FALSE.

Nested implied DO loops are particularly useful when initialising multi-dimensional arrays.

Example

      REAL UPTRI(10,10)
      DATA ((UPTRI(I,J),I=1,J),J=1,10) /55*1.0/

This DATA statement initialises the upper triangular part of the square matrix (two-dimensional array) UPTRI to 1.0. The rest of the matrix is undefined.

1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0
1.0 1.0 1.0
1.0 1.0
1.0

DATA Statements in Procedures

In the main program unit, a nonexecutable DATA statement has the same effect as a bunch of assignment statements at the very beginning of the program.

Example

      PROGRAM MAIN
      CHARACTER*20 NAME
      REAL         DEC,MAG,RA
      DATA NAME,MAG,RA,DEC /'Alpha Centauri',-0.27,14.66,-60.84/

is equivalent to

      PROGRAM MAIN
      CHARACTER*20 NAME
      REAL         DEC,MAG,RA
      NAME = 'Alpha Centauri'
      MAG  = -0.27
      RA   = 14.66
      DEC  = -60.84

However, this does not hold true in procedures. In an external function or subroutine, the DATA statement sets the values exactly once, before the procedure is called, whereas assignment statements are executed every time the procedure is called. This can be useful if there are certain actions which need to happen the first time a procedure is called but not subsequently.

Example

      SUBROUTINE ONEREC(UNITNO,RECORD)
      INTEGER UNITNO
      REAL    RECORD
      LOGICAL OPENED
      DATA    OPENED /.FALSE./
      SAVE    OPENED
      IF (.NOT. OPENED) THEN
         OPEN(UNITNO,FILE='inputfile.dat',STATUS='old',ERR=999)
         OPENED = .TRUE.
      END IF
      READ(UNITNO,*)RECORD
      RETURN
  999 STOP 'Error opening file'
      END

The first time the subroutine is called, the LOGICAL variable OPENED is initialised to .FALSE. Therefore, the logical expression .NOT. OPENED is .TRUE. on the first call and the block IF statement is executed. A file is opened and the variable OPENED is reset to .TRUE.. Then RECORD is read in from the opened file and the subroutine returns to the calling program. On subsequent calls to this subroutine, the logical expression in the block IF will always be .FALSE. and the subroutine will only read in another value into RECORD. This is because the SAVE command preserves the value of OPENED between calls to the subroutine.

Note that DATA cannot be used to initialise variables or arrays which are dummy arguments in the procedure. DATA cannot be used to initialise values in blank COMMON blocks but can be used in the special BLOCK DATA subroutine to initialise variables in named COMMON blocks.