|Fortran 77 Language Reference|
Data Types and Data Items
This chapter describes the data types and data structures in Sun FORTRAN 77.
Nonstandard features are tagged with a small black cross ().
Except for specifically typeless constants, any constant, constant expression, variable, array, array element, substring, or function usually represents typed data.
On the other hand, data types are not associated with the names of programs or subroutines, block data routines, common blocks, namelist groups, or structured records.
Rules for Data Typing
The name determines the type; that is, the name of a datum or function determines its data type, explicitly or implicitly, according to the following rules of data typing;
- A symbolic name of a constant, variable, array, or function has only one data type for each program unit, except for generic functions.
- If you explicitly list a name in a type statement, then that determines the data type.
- If you do not explicitly list a name in a type statement, then the first letter of the name determines the data type implicitly.
- The default implicit typing rule is that if the first letter of the name is
N, then the data type is integer, otherwise it is real.
- You can change the default-implied types by using the
IMPLICITstatement, even to the extent of turning off all implicit typing with the
NONEstatement. You can also turn off all implicit typing by specifying the
-ucompiler flag on the command line; this is equivalent to beginning each program unit with the
An array element has the same type as the array name.
Each intrinsic function has a specified type. An intrinsic function does not require an explicit type statement, but that is allowed. A generic function does not have a predetermined type; the type is determined by the type of the arguments, as shown in Intrinsic Functions.
An external function can have its type specified in any of the following ways:
- Explicitly by putting its name in a type statement
- Explicitly in its
FUNCTIONstatement, by preceding the word
FUNCTIONwith the name of a data type
- Implicitly by its name, as with variables
Implicit typing can affect the type of a function, either by default implicit typing or by an
IMPLICITstatement. You must make the data type of the function be the same within the function subprogram as it is in the calling program unit. The
f77compiler does no type checking across program units.
Properties of Data Types
This section describes the data types in Sun FORTRAN 77.
Default data declarations, those that do not explicitly declare a data size can have their meanings changed by certain compiler options. The next section, Size and Alignment of Data Types summarizes data sizes and alignments and the effects of these options.
BYTEdata type provides a data type that uses only one byte of storage. It is a logical data type, and has the synonym,
A variable of type
BYTEcan hold any of the following:
If it is interpreted as a logical value, a value of 0 represents
.FALSE., and any other value is interpreted as
BYTEtype as an array index, just as it allows the
REALtype, but it does not allow
DOloop index (where it allows only
PRECISION). Wherever the compiler expects
INTEGERexplicitly, it will not allow
BYTEitem occupies 1 byte (8 bits) of storage, and is aligned on 1-byte boundaries.
The character data type,
CHARACTER, which has the synonym,
CHARACTER*1, holds one character.
The character is enclosed in apostrophes (') or quotes (
"). Allowing quotes (") is nonstandard; if you compile with the
-xloption, quotes mean something else, and you must use apostrophes to enclose a string.
The data of type
CHARACTERis always unsigned. A
CHARACTERitem occupies 1 byte (8 bits) of storage and is aligned on 1-byte boundaries.
The character string data type,
CHARACTER*n, where n > 0, holds a string of n characters.
CHARACTER*n data type occupies n bytes of storage and is aligned on 1-byte boundaries.
Every character string constant is aligned on 2-byte boundaries. If it does not appear in a
DATAstatement, it is followed by a null character to ease communication with C routines.
A complex datum is an approximation of a complex number. The complex data type,
COMPLEX, which defaults to a synonym for
COMPLEX*8, is a pair of
REAL*4values that represent a complex number. The first element represents the real part and the second represents the imaginary part.
The default size for a
COMPLEXitem (no size specified) is 8 bytes. The default alignment is on 4-byte boundaries. However, these defaults can be changed by compiling with certain special options (see Size and Alignment of Data Types).
The complex data type
COMPLEX*8is a synonym for
COMPLEX, except that it always has a size of 8 bytes, independent of any compiler options.
The complex data type
COMPLEX*16is a synonym for
COMPLEX, except that it always has a size of 16 bytes, independent of any compiler options.
(SPARC only) The complex data type
COMPLEX*32is a quadruple-precision complex. It is a pair of
REAL*16elements, where each has a sign bit, a 15-bit exponent, and a 112-bit fraction. These
REAL*16elements in f77 conform to the IEEE standard.
The size for
COMPLEX*32is 32 bytes.
The complex data type,
COMPLEX, which usually has the synonym,
COMPLEX*16, is a pair of
REAL*8) values that represents a complex number. The first element represents the real part; the second represents the imaginary part.
The default size for
COMPLEXwith no size specified is 16.
A double-precision datum is an approximation of a real number. The double-precision data type,
PRECISION, which has the synonym,
REAL*8, holds one double-precision datum.
The default size for
PRECISIONwith no size specified is 8 bytes.
PRECISIONelement has a sign bit, an 11-bit exponent, and a 52-bit fraction. These
PRECISIONelements in f77 conform to the IEEE standard for double-precision floating-point data. The layout is shown in Data Representations.
The integer data type,
INTEGER, holds a signed integer.
The default size for
INTEGERwith no size specified is 4, and is aligned on 4-byte boundaries. However, these defaults can be changed by compiling with certain special options (see Size and Alignment of Data Types).
The short integer data type,
INTEGER*2, holds a signed integer. An expression involving only objects of type
INTEGER*2is of that type. Using this feature may have adverse performance implications, and is not recommended.
Generic functions return short or long integers depending on the default integer type. If a procedure is compiled with the
-i2flag, all integer constants that fit and all variables of type
INTEGER(no explicit size) are of type
INTEGER*2. If the precision of an integer-valued intrinsic function is not determined by the generic function rules, one is chosen that returns the prevailing length (
INTEGER*2) when the
-i2compilation option is in effect. With
-i2, the default length of
LOGICALquantities is 2 bytes.
Ordinary integers follow the FORTRAN rules about occupying the same space as a
REALvariable. They are assumed to be equivalent to the C type
int, and 2-byte integers are of C type
int. These short integer and logical quantities do not obey the standard rules for storage association.
INTEGER*2occupies 2 bytes.
INTEGER*2is aligned on 2-byte boundaries.
The integer data type,
INTEGER*4, holds a signed integer.
INTEGER*4occupies 4 bytes.
INTEGER*4is aligned on 4-byte boundaries.
The integer data type,
INTEGER*8, holds a signed 64-bit integer.
INTEGER*8occupies 8 bytes.
INTEGER*8is aligned on 8-byte boundaries.
The logical data type,
LOGICAL, holds a logical value
.FALSE.The value 0 represents
.FALSE.; any other value represents
The usual default size for an
LOGICALitem with no size specified is 4, and is aligned on 4-byte boundaries. However, these defaults can be changed by compiling with certain special options.
The one-byte logical data type,
LOGICAL*1, which has the synonym,
BYTE, can hold any of the following:
LOGICAL*1item occupies one byte of storage.
LOGICAL*1is aligned on one-byte boundaries.
The data type,
LOGICAL*2, holds logical value
.FALSE.The value is defined as for
LOGICAL*2occupies 2 bytes.
LOGICAL*2is aligned on 2-byte boundaries.
The logical data type,
LOGICAL*4holds a logical value
.FALSE.The value is defined as for
LOGICAL*4occupies 4 bytes.
LOGICAL*4is aligned on 4-byte boundaries.
The logical data type,
LOGICAL*8, holds the logical value
.FALSE.The value is defined the same way as for the
LOGICAL*8occupies 8 bytes.
LOGICAL*8is aligned on 8-byte boundaries.
A real datum is an approximation of a real number. The real data type, REAL, which usually has the synonym, REAL*4, holds one real datum.
The usual default size for a REAL item with no size specified is 4 bytes, and is aligned on 4-byte boundaries. However, these defaults can be changed by compiling with certain special options.
A REAL element has a sign bit, an 8-bit exponent, and a 23-bit fraction. These REAL elements in f77 conform to the IEEE standard.
The REAL*4 data type is a synonym for REAL, except that it always has a size of 4 bytes, independent of any compiler options.
The REAL*8, data type is a synonym for DOUBLE PRECISION, except that it always has a size of 8 bytes, independent of any compiler options.
(SPARC only) The
REAL*16data type is a quadruple-precision real. The size for a
REAL*16item is 16 bytes. A
REAL*16element has a sign bit, a 15-bit exponent, and a 112-bit fraction. These
REAL*16elements in f77 conform to the IEEE standard for extended precision.
Size and Alignment of Data Types
Storage and alignment are always given in bytes. Values that can fit into a single byte are byte-aligned.
The size and alignment of types depends on various compiler options and platforms, and how variables are declared. The maximum alignment in COMMON blocks is to 4-byte boundaries.
Default data alignment and storage allocation can be changed by compiling with special options, such as
-xtypemap. The default descriptions in this manual assume that these options are not in force.
Refer to the Fortran User's Guide for details of specific compiler options.
The following table summarizes the default size and alignment, ignoring other aspects of types and options.
TABLE 2-1 Default Data Sizes and Alignments (in Bytes)
DOUBLE COMPLEX X
DOUBLE PRECISION X
Note the following:
COMPLEX*32are only available on SPARC only. In 64-bit environments (compiling with
v9a) the default alignment is on 16-byte (rather than 8-byte) boundaries, as indicated by 8/16 in the table.
- Arrays and structures align according to their elements or fields. An array aligns the same as the array element. A structure aligns the same as the field with the widest alignment.
Compiling with options
-dblchanges the defaults for certain data declarations that appear without an explicit size:
TABLE 2-2 Data Defaults Changed by
-i2, -r8, -dbl
Do not combine
-r8as this can produce unexpected results.
COMPLEX*32are SPARC only.
LOGICALare allocated the larger space indicated above. This is done to maintain the FORTRAN requirement that an integer item and a real item have the same amount of storage. However, with
-r88 bytes are allocated but only 4-byte arithmetic is done. With
-dbl, 8 bytes are allocated and full 8-byte arithmetic is done. In all other ways,
-r8produce the same results. A disadvantage of using
-dblis that it also promotes
DOUBLE PRECISIONdata to
QUAD PRECISION, possibly degrading performance.
Use of the more flexible
-xtypemapoption is preferred over the older
integer:mixedindicates 8 byte integers but only 4 byte arithmetic.
There are two additional possibilities on SPARC:
which map both default
DOUBLEto 8 bytes, and should be preferable over using
LOGICALare treated the same, and
COMPLEXis mapped as two
COMPLEXwill be treated the way
-dalign(SPARC only) force alignment of all 8, 16, or 32-byte data onto 8-byte boundaries. Option
-dbl_align_allcauses all data to be aligned on 8-byte boundaries. Programs that depend on the use of these options may not be portable.
See the Fortran User's Guide for details on these compiler options.
A literal constant is a datum whose value cannot change throughout the program unit. The form of the string representing a constant determines the value and data type of the constant. (For a named constant, defined by a
PARAMETERstatement, the name defines the data type.)
There are three general kinds of constants:
Blank characters within an arithmetic or logical constant do not affect the value of the constant. Within character constants, they do affect the value.
A signed constant is an arithmetic constant with a leading plus or minus sign. An unsigned constant is an arithmetic constant without a leading sign.
For integer, real, and double-precision data, zero is neither positive nor negative. The value of a signed zero is the same as that of an unsigned zero.
Compiling with any of the options
-xtypemapalters the default size of integer, real, complex, and double precision constants. These options are described in Chapter 2, and in the Fortran User's Guide.
A character-string constant is a string of characters enclosed in apostrophes or quotes. The apostrophes are standard; the quotes are not.
If you compile with the
-xloption, then the quotes mean something else, and you must use apostrophes to enclose a string.
If a string begins with one kind of delimiter, the other kind can be embedded within it without using the repeated quote or backslash escapes. See TABLE 2-3.
Each character string constant appearing outside a
DATAstatement is followed by a null character to ease communication with C routines. You can make character string constants consisting of no characters, but only as arguments being passed to a subprogram. Such zero length character string constants are not FORTRAN standard.
However, if you put such a null character constant into a character variable, the variable will contain a blank, and have a length of at least 1 byte.
Example: Length of null character string:
cat NulVar.fcharacter*1 x / 'a' /, y / '' /, z / 'c' /write(*,*) x, y, zwrite(*,*) len( y )enddemo%
For compatibility with C usage, the following backslash escapes are recognized. If you include the escape sequence in a character string, then you get the indicated character.
TABLE 2-3 Backslash Escape Sequences
Apostrophe, which does not terminate a string
Quotation mark, which does not terminate a string
x, where x is any other character
If you compile with the
-xloption, then the backslash character (
\) is treated as an ordinary character. That is, with the
-xloption, you cannot use these escape sequences to get special characters.
Technically, the escape sequences are not nonstandard, but are implementation- defined.
A complex constant is an ordered pair of real or integer constants (or
PARAMETERconstants). The constants are separated by a comma, and the pair is enclosed in parentheses. The first constant is the real part, and the second is the imaginary part. A complex constant,
COMPLEX*8, uses 8 bytes of storage.
A double-complex constant,
COMPLEX*16, is an ordered pair of real or integer constants, where one of the constants is
REAL*8, and the other is
The constants are separated by a comma, and the pair is enclosed in parentheses. The first constant is the real part, and the second is the imaginary part. A double-complex constant,
COMPLEX*16, uses 16 bytes of storage.
COMPLEX*32(Quad Complex) Constants
(SPARC only) A quad complex constant is an ordered pair of real or integer constants, where one of the constants is
REAL*16, and the other is
The constants are separated by a comma, and the pair is enclosed in parentheses. The first constant is the real part, and the second is the imaginary part. A quad complex constant,
COMPLEX*32, uses 32 bytes of storage.
Example: Quad complex constants (SPARC only):
( 9.01Q6, .603 )( +1.0, -2.0Q0 )( 1Q0, 2 )( 3.3Q-4932, 9 )( 1, 1.1Q+4932 )( 4.51Q6, ) Invalid--need second part( +1.0, -2.0 ) Not quad complex --need a REAL*16
An integer constant consists of an optional plus or minus sign, followed by a string of decimal digits.
- No other characters are allowed except, of course, a space.
- If no sign is present, the constant is assumed to be nonnegative.
- The value must be in the
INTEGER*4range (-2147483648, 2147483647), unless compiled with an option that promotes integers to 64 bits, in which case the range becomes
INTEGER*8(-9223372036854775808,9223372036854775807). See Size and Alignment of Data Types.
Example: Integer constants:
-2147483648-2147483649 Invalid--too small, error message-100+199290022.71828 Not INTEGER--decimal point not allowed1E6 Not INTEGER--E not allowed29,002 Invalid--comma not allowed, error message21474836472147483648 Invalid-- too large, error message
Alternate Octal Notation
You can also specify integer constants with the following alternate octal notation. Precede an integer string with a double quote (") and compile with the
-xloption. These are octal constants of type
You can also specify typeless constants as binary, octal, hexadecimal, or Hollerith. See Typeless Constants (Binary, Octal, Hexadecimal).
Compiling with an option that promotes the range from
INTEGER*4(-21474836, 21474836) to
INTEGER*8(-9223372036854775808, 9223372036854775807). The integer constant is stored or passed as an 8-byte integer, data type
If a constant argument is in the range (-32768, 32767), it is usually widened to a 4-byte integer, data type
INTEGER*4; but compiling with the
-i2option will cause it to be stored or passed as a 2-byte integer, data type
A logical constant is either the logical value true or false. The only logical constants are
.FALSE.; no others are possible. The period delimiters are necessary.
A logical constant takes 4 bytes of storage. If it is an actual argument, it is passed as 4 bytes, unless compiled with the
-i2option, in which case it is passed as 2.
A real constant is an approximation of a real number. It can be positive, negative, or zero. It has a decimal point or an exponent. If no sign is present, the constant is assumed to be nonnegative.
REAL*4, use 4 bytes of storage.
Basic Real Constant
A basic real constant consists of an optional plus or minus sign, followed by an integer part, followed by a decimal point, followed by a fractional part.
The integer part and the fractional part are each strings of digits, and you can omit either of these parts, but not both.
A real exponent consists of the letter
E, followed by an optional plus or minus sign, followed by an integer.
A real constant has one of these forms:
- Basic real constant
- Basic real constant followed by a real exponent
- Integer constant followed by a real exponent
A real exponent denotes a power of ten. The value of a real constant is the product of that power of ten and the constant that precedes the
Example: Real constants:
-32.-32.181.6E-97E31.6E12$1.0E2.0 Invalid-- $ not allowed, error message82 Not REAL--need decimal point or exponent29,002.0 Invalid --comma not allowed, error message1.6E39 Invalid--too large, machine infinity is used1.6E-39 Invalid --too small, some precision is lost
The restrictions are:
- Other than the optional plus or minus sign, a decimal point, the digits 0 through 9, and the letter
E, no other characters are allowed.
- The magnitude of a normalized single-precision floating-point value must be in the approximate range (1.175494E-38, 3.402823E+38).
REAL*8(Double-Precision Real) Constants
A double-precision constant is an approximation of a real number. It can be positive, negative, or zero. If no sign is present, the constant is assumed to be nonnegative. A double-precision constant has a double-precision exponent and an optional decimal point. Double-precision constants,
REAL*8, use 8 bytes of storage. The
REAL*8notation is nonstandard.
A double-precision exponent consists of the letter
D, followed by an optional plus or minus sign, followed by an integer.
A double-precision exponent denotes a power of 10. The value of a double-precision constant is the product of that power of 10 and the constant that precedes the
D. The form and interpretation are the same as for a real exponent, except that a
Dis used instead of an
Examples of double-precision constants are:
--$not allowed, error message82 Not DOUBLE PRECISION--need decimal point or exponent29,002.0D0 Invalid--comma not allowed, error message1.8D308 Invalid--too large, machine infinity is used1.0D-324 Invalid--too small, some precision is lost
The restrictions are:
- Other than the optional plus or minus sign, a decimal point, the digits 0 through 9, a blank, and the letter
D. No other characters are allowed.
- The magnitude of an IEEE normalized double-precision floating-point value must be in the approximate range (2.225074D-308, 1.797693D+308).
REAL*16(Quad Real) Constants
(SPARC only) A quadruple-precision constant is a basic real constant or an integer constant, such that it is followed by a quadruple-precision exponent. See Real Constants.
A quadruple-precision exponent consists of the letter
Q, followed by an optional plus or minus sign, followed by an integer.
A quadruple-precision constant can be positive, negative, or zero. If no sign is present, the constant is assumed to be nonnegative.
Example: Quadruple-precision constants:
1.6Q-97Q33.3Q-49321.1Q+4932$1.0Q2.0 Invalid--$ not allowed, error message82 Not quad--need exponent29,002.0Q0 Invalid--comma not allowed, error message1.6Q5000 Invalid--too large, machine infinity is used1.6Q-5000 Invalid--too small, some precision is lost
The form and interpretation are the same as for a real constant, except that a
Qis used instead of an
The restrictions are:
- Other than the optional plus or minus sign, a decimal point, the digits 0 through 9, a blank, and the letter Q. No other characters are allowed.
- The magnitude of an IEEE normalized quadruple-precision floating-point value must be in the approximate range (3.362Q-4932, 1.20Q+4932).
- It occupies 16 bytes of storage.
- Each such datum is aligned on 8-byte boundaries.
Typeless Constants (Binary, Octal, Hexadecimal)
Typeless numeric constants are so named because their expressions assume data types based on how they are used.
These constants are not converted before use. However, in f77, they must be distinguished from character strings.
The general form is to enclose a string of appropriate digits in apostrophes and prefix it with the letter B, O, X, or Z. The B is for binary, the O is for octal, and the X or Z are for hexadecimal.
Example: Binary, octal, and hexadecimal constants,
PARAMETER ( P1 = Z'1F' )INTEGER*2 N1, N2, N3, N4DATA N1 /B'0011111'/, N2/O'37'/, N3/X'1f'/, N4/Z'1f'/WRITE ( *, 1 ) N1, N2, N3, N4, P11 FORMAT ( 1X, O4, O4, Z4, Z4, Z4 )END
Note the edit descriptors in
Ofor octal, and
Zfor hexadecimal. Each of the above integer constants has the value 31 decimal.
Example: Binary, octal, and hexadecimal, other than in
INTEGER*4 M, ICOUNT/1/, JCOUNTREAL*4 TEMPM = ICOUNT + B'0001000'JCOUNT = ICOUNT + O'777'TEMP = X'FFF99A'WRITE(*,*) M, JCOUNT, TEMPEND
In the above example, the context defines
REAL*4. For a real number, using IEEE floating-point, a given bit pattern yields the same value on different architectures.
You can enter control characters with typeless constants, although the
CHARfunction is standard, and this way is not.
Alternate Notation for Typeless Constants
For compatibility with other versions of FORTRAN, the following alternate notation is allowed for octal and hexadecimal notation. This alternate does not work for binary, nor does it work in
For an octal notation, enclose a string of octal digits in apostrophes and append the letter O.
For hexadecimals, enclose a string of hex digits in apostrophes and append the letter
Here are the rules and restrictions for binary, octal, and hexadecimal constants:
- These constants are for use anywhere numeric constants are allowed.
- These constants are typeless. They are stored in the variables without any conversion to match the type of the variable, but they are stored in the appropriate part of the receiving field--low end, high end.
- If the receiving data type has more digits than are specified in the constant, zeros are filled on the left.
- If the receiving data type has fewer digits than are specified in the constant, digits are truncated on the left. If nonzero digits are lost, an error message is displayed.
- Specified leading zeros are ignored.
- You can specify up to 8 bytes of data for any one constant--at least that's all that are used.
- If a typeless constant is an actual argument, it has no data type, but it is always 4 bytes that are passed.
- For binary constants, each digit must be 0 or 1.
- For octal constants, each digit must be in the range 0 to 7.
- For hexadecimal constants, each digit must be in the range 0 to 9 or in the range A to F, or a to f.
- Outside of
DATAstatements, such constants are treated as the type required by the context. If a typeless constant is used with a binary operator, it gets the data type of the other operand (8.0 + '37'O).
DATAstatements, such constants are treated as typeless binary, hexadecimal, or octal constants.
A Hollerith constant consists of an unsigned, nonzero, integer constant, followed by the letter
H, followed by a string of printable characters where the integer constant designates the number of characters in the string, including any spaces and tabs.
A Hollerith constant occupies 1 byte of storage for each character.
A Hollerith constant is aligned on 2-byte boundaries.
The FORTRAN standard does not have this old Hollerith notation, although the standard recommends implementing the Hollerith feature to improve compatibility with old programs.
Hollerith data can be used in place of character-string constants. They can also be used in
IFtests, and to initialize noncharacter variables in
DATAstatements and assignment statements, though none of these are recommended, and none are standard. These are typeless constants.
The rules and restrictions on Hollerith constants are:
- The number of characters has no practical limit.
- The characters can continue over to a continuation line, but that gets tricky. Short standard fixed format lines are padded on the right with blanks up to 72 columns, but short tab-format lines stop at the newline.
- If a Hollerith constant is used with a binary operator, it gets the data type of the other operand.
- If you assign a Hollerith constant to a variable, and the length of the constant is less than the length of the data type of the variable, then spaces (ASCII 32) are appended on the right.
- If the length of a Hollerith constant or variable is greater than the length of the data type of the variable, then characters are truncated on the right.
- If a Hollerith constant is used as an actual argument, it is passed as a 4-byte item.
- If a Hollerith constant is used, and the context does not determine the data type, then
Fortran 95-Style Constants
The Sun WorkShop Fortran 77 compiler recognizes the Fortran 95-style syntax for integer and real constants that allows literal specification of the size of the data item. In Fortran 95 terminology, a constant literal may include an optional trailing underscore followed by a "kind type parameter".
In the Sun Fortran 77 implementation, the "kind type parameter" is limited to the digits 1, 2, 4, 8, or 16, and its use specifies the data size, in bytes, of the literal constant. For example:
12_8 specifies an 8-byte integer constant, value = 1212.012_16 specifies a 16-byte real constant, value = 12.0121.345E-10_8 specifies an 8-byte real constant, value = 1.345E-10(-1.5_8,.895E-3_8) specifies a complex constant with 8-byte real and imaginary parts
With complex constants, the real and imaginary parts may be specified with different kind type parameters,
(1.0_8,2.0_4), but the resulting data item will have the real and imaginary parts with the same size, taking the larger one specified.
This construction is valuable when calling subprograms with constant arguments when a specific data type is required, as in the following example:
call suby(A,1.5_8,0_8,Y)...subroutine suby(H0, M, N, W)INTEGER *8 M, N,...
A variable is a symbolic name paired with a storage location. A variable has a name, a value, and a type. Whatever datum is stored in the location is the value of the variable. This does not include arrays, array elements, records, or record fields, so this definition is more restrictive than the usual usage of the word "variable."
You can specify the type of a variable in a type statement. If the type is not explicitly specified in a type statement, it is implied by the first letter of the variable name: either by the usual default implied typing, or by any implied typing of
IMPLICITstatements. See Types for more details on the rules for data typing.
At any given time during the execution of a program, a variable is either defined or undefined. If a variable has a predictable value, it is defined; otherwise, it is undefined. A previously defined variable may become undefined, as when a subprogram is exited.
You can define a variable with an assignment statement, an input statement, or a
DATAstatement. If a variable is assigned a value in a
DATAstatement, then it is initially defined.
Two variables are associated if each is associated with the same storage location. You can associate variables by use of
MAPstatements. Actual and dummy arguments can also associate variables.
array is a named collection of elements of the same type. It is a nonempty sequence of data and occupies a group of contiguous storage locations. An array has a name, a set of elements, and a type.
An array name is a symbolic name for the whole sequence of data.
An array element is one member of the sequence of data. Each storage location holds one element of the array.
An array element name is an array name qualified by a subscript. See Array Subscripts for details.
You can declare an array in any of the following statements:
An array declarator specifies the name and properties of an array.
A dimension declarator has the form:
An array must appear only once in an array declarator within a program unit (main program, subroutine, function, or block common). The compiler flags multiple or duplicate array declarations within the same unit as errors.
The number of dimensions in an array is the number of dimension declarators. The minimum number of dimensions is one; the maximum is seven. For an assumed-size array, the last dimension can be an asterisk.
The lower bound indicates the first element of the dimension, and the upper bound indicates the last element of the dimension. In a one-dimensional array, these are the first and last elements of the array.
In the above example,
Vis an array of real numbers, with 1 dimension and 11 elements. The first element is
V(-5); the last element is
In the above example,
Vis an array of real numbers, with 1 dimension and 1000 elements. The first element is
V(1); the last element is
Mhas 12 elements, each of which consists of 7 characters.
Vhas 9 elements, each of which consists of 4 characters.
The following restrictions on bounds apply:
- Both the upper and the lower bounds can be negative, zero, or positive.
- The upper bound must be greater than or equal to the lower bound.
- If only one bound is specified, it is the upper, and the lower is one.
- In assumed-size arrays, the upper bound of the last dimension is an asterisk.
- Each bound is an integer expression, and each operand of the expression is a constant, a dummy argument, or a variable in a common block. No array references or user-defined functions are allowed.
An adjustable array is an array that is a dummy argument or local array with one or more of its dimensions or bounds as an expression of integer variables that are either themselves dummy arguments, or are in a common block.
You can declare adjustable arrays in the usual
DIMENSIONor type statements. In f77, you can also declare adjustable arrays in a
RECORDstatement, if that
RECORDstatement is not inside a structure declaration block.
The restrictions are:
- The size of an adjustable array cannot exceed the size of the corresponding actual argument.
- In the first caller of the call sequence, the corresponding array must be dimensioned with constants.
- You cannot declare an adjustable array in
If the array is local to the routine, memory is allocated on entry to the routine and deallocated on return to the caller.
An assumed-size array is an array that is a dummy argument, and which has an asterisk as the upper bound of the last dimension.
You can declare assumed-size arrays in the usual
COMMON, or type statements.
f77extensions allow you to:
- declare assumed-size arrays in a
RECORDstatement, if that
RECORDstatement is not inside a structure declaration block.
- use an assumed-size array as a unit identifier for an internal file in an I/O statement.
- use an assumed-size array as a runtime format specifier in an I/O statement.
An assumed-size array cannot be used in an I/O list.
Array Names with No Subscripts
An array name with no subscripts indicates the entire array. It can appear in any of the following statements:
EQUIVALENCEstatement, the array name without subscripts indicates the first element of the array.
An array element name is an array name qualified by a subscript.
Form of a Subscript
A subscript is a parenthesized list of subscript expressions. There must be one subscript expression for each dimension of the array.
The form of a subscript is:
] ... )
where s is a subscript expression. The parentheses are part of the subscript.
The above code assigns
0.0to the element in row 1, column 2, of array
Subscript expressions have the following properties and restrictions:
- A subscript expression is an integer, real, complex, logical, or byte expression. According to the FORTRAN Standard, it must be an integer expression.
- A subscript expression can contain array element references and function references.
- Evaluation of a function reference must not alter the value of any other subscript expression within the same subscript.
- Each subscript expression is an index into the appropriate dimension of the array.
- Each subscript expression must be within the bounds for the appropriate dimension of the array.
- A subscript of the form ( L1, ..., Ln ), where each Li is the lower bound of the respective dimension, references the first element of the array.
- A subscript of the form (U1, ..., Un), where each Ui is the upper bound of the respective dimension, references the last element of the array.
- Array element
A(n)is not necessarily the nth element of array
REAL V(-1:8)V(2) = 0.0
In the above example, the fourth element of
Vis set to zero.
Subscript expressions cannot exceed the range of
INTEGER*4in 32-bit environments. It is not controlled, but if the subscript expression is not in the range
(-2147483648, 2147483647), then the results are unpredictable. When compiled for 64-bit environments,
INTEGER*8subscript expressions are allowed.
Array elements are usually considered as being arranged with the first subscript as the row number and the second subscript as the column number. This corresponds to traditional mathematical nxm matrix notation:
a1,1 a1,2 a1,3 ... a1,m a2,1 a2,2 ... a2,m ... ... ai,j ... ai,m an,1 an,2 ... an,m
Element ai,j is located in row i, column j.
Array elements are stored in column-major order.
The inner (leftmost) subscript changes more rapidly.
A character datum is a sequence of one or more characters. A character substring is a contiguous portion of a character variable or of a character array element or of a character field of a structured record.
A substring name can be in either of the following two forms:
] : [e2
] ... ) ( [e1
] : [e2
Both e1 and e2 are integer expressions. They cannot exceed the range of
INTEGER*4on 32-bit environments. If the expression is not in the range (-2147483648, 2147483647), then the results are unpredictable. When compiled for 64-bit environments, the substring character position expressions can be in the range of
In the above example, there are L-I+1 characters in the substring.
In the above example, there are N-M+1 characters in the substring.
Here are the rules and restrictions for substrings:
- Character positions within a substring are numbered from left to right.
- The first character position is numbered 1, not 0.
- The initial and last character positions must be integer expressions.
- If the first expression is omitted, it is 1.
- If the second expression is omitted, it is the declared length.
- The result is undefined unless 0 < L the declared length, where I is the initial position, and L is the last position.
- Substrings can be used on the left and right sides of assignments and as procedure actual arguments.
- Substrings must not be overlapping.
ASTR(2:4) = ASTR(3:5)is illegal.
Examples: Substrings--the value of the element in column 2, row 3 is e23:
cat sub.fcharacter v*8 / 'abcdefgh' /,& m(2,3)*3 / 'e11', 'e21',& 'e12', 'e22',& 'e13', 'e23' /print *, v(3:5)print *, v(1:)print *, v(:8)print *, v(:)print *, m(1,1)print *, m(2,1)print *, m(1,2)print *, m(2,2)print *, m(1,3)print *, m(2,3)print *, m(1,3)(2:3)enddemo%
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
RECORDstatements, as explained in the following subsections.
The structure declaration has the following syntax:
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
In the above example, a structure named
PRODUCTis defined to consist of the five fields
PRICE. For an example with a field-list, see Structure Within a Structure.
Rules and Restrictions for Structures
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
STRUCTUREstatement and the
STRUCTUREstatement are field-declaration statements and
PARAMETERstatement inside a structure declaration block is equivalent to one outside.
Rules and Restrictions for Fields
Fields that are type declarations use the identical syntax of normal
FORTRANtype statements. All
f77types are allowed, subject to the following rules and restrictions:
- Any dimensioning needed must be in the type statement. The
DIMENSIONstatement has no effect on field names.
- You can specify the pseudo-name
%FILLfor a field name.
%FILLis provided for compatibility with other versions of
FORTRAN. It is not needed in
f77because 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
%FILLdoes is provide a field of the specified size and type, and preclude referencing it.
- You must explicitly type all field names. The
IMPLICITstatement does not apply to statements in a
STRUCTUREdeclaration, nor do the implicit
- You cannot use arrays with adjustable or assumed size in field declarations, nor can you include passed-length
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 Data Representations for a summary of storage allocation.
RECORDstatement declares variables to be records with a specified structure, or declares arrays to be arrays of such records.
Each of the three variables,
NEXT, is a record which has the
LINEis 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
- Records and record fields are not allowed in
NAMELISTstatements. Record fields are not allowed in
Record and Field Reference
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.
Example: References that are based on structure and records of the above two examples:
...RECORD /PRODUCT/ CURRENT, PRIOR, NEXT, LINE(10)...CURRENT = NEXTLINE(1) = CURRENTWRITE ( 9 ) CURRENTNEXT.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
IDof one record to 82.
Example: Structure and record declarations, record and field assignments:
cat str1.f* str1.f Simple structureSTRUCTURE / S /INTEGER*4 IREAL*4 REND STRUCTURERECORD / S / R1, R2R1.I = 82R1.R = 2.7182818R2 = R1WRITE ( *, * ) R2.I, R2.RSTOPENDdemo%
f77 -silent str1.fdemo%
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:
RECORDdeclaration within a structure declaration
- A structure declaration within a structure declaration (nesting)
Record Within a Structure
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.
In the above example, the structure
SALEcontains three fields,
ITEMis a record with the structure,
Structure Within a Structure
You can nest a declaration within a declaration.
/PRODUCT/is not declared previously, then you can declare it within the declaration of
STRUCTURE /SALE/CHARACTER*32 BUYERINTEGER*2 QUANTITYSTRUCTURE /PRODUCT/ ITEMINTEGER*4 IDCHARACTER*16 NAMECHARACTER*8 MODELREAL*4 COSTREAL*4 PRICEEND STRUCTUREEND STRUCTURE
Here, the structure
SALEstill contains the same three fields as in the prior example:
ITEM. The field
ITEMis 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.
Field Reference in Substructures
You can refer to fields within substructures.
Rules and Restrictions for Substructures
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.
Unions and Maps
A union declaration defines groups of fields that share memory at runtime.
Fields in a Map
Each field-declaration in a map declaration can be one of the following:
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
STRUCTURE /STUDENT/CHARACTER*32 NAMEINTEGER*2 CLASSUNIONMAPCHARACTER*16 MAJOREND MAPMAPINTEGER*2 CREDITSCHARACTER*8 GRAD_DATEEND MAPEND UNIONEND STRUCTURE
If you define the variable
PERSONto have the structure
/STUDENT/from the above example, then
PERSON.MAJORreferences a field from the first map, and
PERSON.CREDITSreferences 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.
POINTERstatement establishes pairs of variables and pointers. Each pointer contains the address of its paired variable.
A pointer-based variable is a variable paired with a pointer in a
POINTERstatement. A pointer-based variable is usually just called a based variable, or a pointee. The pointer is the integer variable that contains the address. (Variable names appearing on a
POINTERstatement are considered
VOLATILEby the compiler.)
Here, V is a pointee, and P is its associated pointer.
See POINTER, for more examples.
Usage of Pointers
Normal use of pointer-based variables involves the following steps. The first two steps can be in either order.1. Define the pairing of the pointer-based variable and the pointer in a
POINTERstatement.2. Define the type of the pointer-based variable.
- The pointer itself is integer type and should not appear in a type declaration.3. Set the pointer to the address of an area of memory that has the appropriate size and type.
- You do not normally do anything else explicitly with the pointer.4. Reference the pointer-based variable.
- Just use the pointer-based variable in normal FORTRAN statements--the address of that variable is always from its associated pointer.
Address and Memory
No storage for the variable is allocated when a pointer-based variable is defined, so you must provide an address of a variable of the appropriate type and size, and assign the address to a pointer, usually with the normal assignment statement or data statement.
free()routines associate and deassociate memory addresses with pointers. (These routines are described in Chapter 6.)
When compiled for 64-bit environments, pointers declared by the
You can obtain the address from the intrinsic function
In the above example, the
CHARACTERstatement allocates 12 bytes of storage for
A, but no storage for
V. It merely specifies the type of
Vis a pointer-based variable, then assign the address of
P, so now any use of
Vwill refer to
Aby the pointer
P. The program prints an
When compiled for 64-bit environments,
INTEGER*8value. The receiving variable must be either a pointer or an
INTEGER*8variable to avoid possible address truncation.
Memory and Address by
MALLOC()allocates an area of memory and returns the address of the start of that area. The argument to the function is an integer specifying the amount of memory to be allocated, in bytes. If successful, it returns a pointer to the first item of the region; otherwise, it returns an integer 0. The region of memory is not initialized in any way.
In the above example,
MALLOC()allocates 10,000 bytes of memory and associates the address of that block of memory with the pointer P1.
Deallocation of Memory by
FREE()deallocates a region of memory previously allocated by
MALLOC(). The argument given to
FREE()must be a pointer previously returned by
MALLOC(), but not already given to
FREE(). The memory is returned to the memory manager, making it unavailable to the programmer.
In the above example,
MALLOC()allocates 10,000 bytes of memory, which are associated with pointer
FREE()later returns those same 10,000 bytes to the memory manager.
Here are some special considerations when working with pointers and memory allocation with
- The pointers are of type integer, and are automatically typed that way by the compiler. You must not type them yourself.
- A pointer-based variable cannot itself be a pointer.
- The pointer-based variables can be of any type, including structures.
- No storage is allocated when such a pointer-based variable is declared, even if there is a size specification in the type statement.
- You cannot use a pointer-based variable as a dummy argument or in
- The dimension expressions for pointer-based variables must be constant expressions in main programs. In subroutines and functions, the same rules apply for pointer-based array variables as for dummy arguments--the expression can contain dummy arguments and variables in common. Any variables in the expressions must be defined with an integer value at the time the subroutine or function is called.
- Address expressions cannot exceed the range of
INTEGER*4on 32-bit environments. If the expression is not in the range (-2147483648, 2147483647), then the results are unpredictable.
- When compiling for 64-bit environments, use
malloc64()to access the 64-bit address space. Routine
INTEGER*8argument and returns a 64-bit pointer value. In 64-bit programs, pointers defined by the
POINTERstatement are 64-bit
INTEGER*8values. See the Fortran Library Reference Manual and the malloc(3F) man pages.
Optimization and Pointers
Pointers have the annoying side effect of reducing the assumptions that the global optimizer can make. For one thing, compare the following:
- Without pointers, if you call a subroutine or function, the optimizer knows that the call will change only variables in common or those passed as arguments to that call.
- With pointers, this is no longer valid, since a routine can take the address of an argument and save it in a pointer in common for use in a subsequent call to itself or to another routine.
Therefore, the optimizer must assume that a variable passed as an argument in a subroutine or function call can be changed by any other call. Such an unrestricted use of pointers would degrade optimization for the vast majority of programs that do not use pointers.
There are two alternatives for optimization with pointers.
- Do not use pointers with optimization level
- Use a pointer only to identify the location of the data for calculations and pass the pointer to a subprogram. Almost anything else you do to the pointer can yield incorrect results.
The second choice also has a suboption: localize pointers to one routine and do not optimize it, but do optimize the routines that do the calculations. If you put the calling the routines on different files, you can optimize one and not optimize the other.
Example: A relatively "safe" kind of coding with
REAL A, B, V(100,100) This programming unit doesPOINTER ( P, V ) nothing else with P other thanP = MALLOC(10000) getting the address and passing it....CALL CALC ( P, A )...ENDSUBROUTINE CALC ( ARRAY, X )...RETURNEND
If you want to optimize only
-O4, then avoid using pointers in
Some Problematic Code Practices
Any of the following coding practices, and many others, could cause problems with an optimization level of
- A program unit does arithmetic with the pointer.
- A subprogram saves the address of any of its arguments between calls.
- A function returns the address of any of its arguments, although it can return the value of a pointer argument.
- A variable is referenced through a pointer, but the address of the variable is not explicitly taken with the
The compiler assumes that a reference through
A, but not
B; this assumption could produce incorrect code.
Sun Microsystems, Inc.
Copyright information. All rights reserved.
|Library | Contents | Previous | Next | Index|