Lady Ada

Ada '83 Language Reference Manual

Copyright 1980, 1982, 1983 owned by the United States Government. Direct reproduction and usage requests to the Ada Information Clearinghouse.

3.6. Array Types


An array object is a composite object consisting of components that have the same subtype. The name for a component of an array uses one or more index values belonging to specified discrete types. The value of an array object is a composite value consisting of the values of its components.

    array_type_definition ::=
       unconstrained_array_definition | constrained_array_definition 
    unconstrained_array_definition ::=
       array(index_subtype_definition {, index_subtype_definition}) of
    constrained_array_definition ::=
       array index_constraint of component_subtype_indication 
    index_subtype_definition ::= type_mark range <> 
    index_constraint ::=  (discrete_range {, discrete_range}) 
    discrete_range ::= discrete_subtype_indication | range   

An array object is characterized by the number of indices (the dimensionality of the array), the type and position of each index, the lower and upper bounds for each index, and the type and possible constraint of the components. The order of the indices is significant.

A one-dimensional array has a distinct component for each possible index value. A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order). The possible values for a given index are all the values between the lower and upper bounds, inclusive; this range of values is called the index range.

An unconstrained array definition defines an array type. For each object that has the array type, the number of indices, the type and position of each index, and the subtype of the components are as in the type definition; the values of the lower and upper bounds for each index belong to the corresponding index subtype, except for null arrays as explained in section 3.6.1. The index subtype for a given index position is, by definition, the subtype denoted by the type mark of the corresponding index subtype definition. The compound delimiter <> (called a box) of an index subtype definition stands for an undefined range (different objects of the type need not have the same bounds). The elaboration of an unconstrained array definition creates an array type; this elaboration includes that of the component subtype indication.

A constrained array definition defines both an array type and a subtype of this type:

If a constrained array definition is given for a type declaration, the simple name declared by this declaration denotes the array subtype.

The elaboration of a constrained array definition creates the corresponding array type and array subtype. For this elaboration, the index constraint and the component subtype indication are elaborated. The evaluation of each discrete range of the index constraint and the elaboration of the component subtype indication are performed in some order that is not defined by the language.

Examples of type declarations with unconstrained array definitions:

    type VECTOR     is array(INTEGER  range <>) of REAL;
    type MATRIX     is array(INTEGER  range <>, INTEGER range <>) of REAL;
    type BIT_VECTOR is array(INTEGER  range <>) of BOOLEAN;
    type ROMAN      is array(POSITIVE range <>) of ROMAN_DIGIT; 

Examples of type declarations with constrained array definitions:

    type TABLE    is array(1 .. 10) of INTEGER;
    type SCHEDULE is array(DAY) of BOOLEAN;
    type LINE     is array(1 .. MAX_LINE_SIZE) of CHARACTER;  

Examples of object declarations with constrained array definitions:

    GRID : array(1 .. 80, 1 .. 100) of BOOLEAN;
    MIX  : array(COLOR range RED .. GREEN) of BOOLEAN;
    PAGE : array(1 .. 50) of LINE;  --  an array of arrays                                                    


For a one-dimensional array, the rule given means that a type declaration with a constrained array definition such as

    type T is array(POSITIVE range MIN .. MAX) of COMPONENT; 

is equivalent (in the absence of an incorrect order dependence) to the succession of declarations

    subtype index_subtype is POSITIVE range MIN .. MAX;
    type array_type is array(index_subtype range <>) of COMPONENT;
    subtype T is array_type (index_subtype); 

where index_subtype and array_type are both anonymous. Consequently, T is the name of a subtype and all objects declared with this type mark are arrays that have the same bounds. Similar transformations apply to multidimensional arrays.

A similar transformation applies to an object whose declaration includes a constrained array definition. A consequence of this is that no two such objects have the same type.

References: anonymous type, bound of a range, component, constraint, discrete type, elaboration, and 3.9, in some order, name, object, range, subtype, subtype indication, type, type declaration, type definition, type mark.

Rationale references: 4.5 Array Types

Style Guide references: 5.3.2 Anonymous Types, 5.5.1 Range Values, 5.5.2 Array Attributes, 5.9.3 Dependence on Parameter Passing Mechanism, 8.2.2 Unconstrained Arrays, 8.3.4 Using Generic Units for Abstract Data Types, 9.1.3 Arrays


3.6.1. Index Constraints and Discrete Ranges


An index constraint determines the range of possible values for every index of an array type, and thereby the corresponding array bounds.

For a discrete range used in a constrained array definition and defined by a range, an implicit conversion to the predefined type INTEGER is assumed if each bound is either a numeric literal, a named number, or an attribute, and the type of both bounds (prior to the implicit conversion) is the type universal_integer. Otherwise, both bounds must be of the same discrete type, other than universal_integer; this type must be determinable independently of the context, but using the fact that the type must be discrete and that both bounds must have the same type. These rules apply also to a discrete range used in an iteration rule (see 5.5) or in the declaration of a family of entries (see 9.5).

If an index constraint follows a type mark in a subtype indication, then the type or subtype denoted by the type mark must not already impose an index constraint. The type mark must denote either an unconstrained array type or an access type whose designated type is such an array type. In either case, the index constraint must provide a discrete range for each index of the array type and the type of each discrete range must be the same as that of the corresponding index.

An index constraint is compatible with the type denoted by the type mark if and only if the constraint defined by each discrete range is compatible with the corresponding index subtype. If any of the discrete ranges defines a null range, any array thus constrained is a null array, having no components. An array value satisfies an index constraint if at each index position the array value and the index constraint have the same index bounds. (Note, however, that assignment and certain other operations on arrays involve an implicit subtype conversion.)

The bounds of each array object are determined as follows:

For the elaboration of an index constraint, the discrete ranges are evaluated in some order that is not defined by the language.

Examples of array declarations including an index constraint:

    BOARD     : MATRIX(1 .. 8,  1 .. 8);  --  see 3.6
    RECTANGLE : MATRIX(1 .. 20, 1 .. 30);
    INVERSE   : MATRIX(1 .. N,  1 .. N);  --  N need not be static 

    FILTER    : BIT_VECTOR(0 .. 31); 

Example of array declaration with a constrained array subtype:

    MY_SCHEDULE : SCHEDULE;  --  all arrays of type SCHEDULE have the same

Example of record type with a component that is an array:

          IMAGE : STRING(1 .. LENGTH);
       end record; 

    NULL_LINE : VAR_LINE(0);  --  NULL_LINE.IMAGE is a null array      


The elaboration of a subtype indication consisting of a type mark followed by an index constraint checks the compatibility of the index constraint with the type mark (see 3.3.2).

All components of an array have the same subtype. In particular, for an array of components that are one-dimensional arrays, this means that all components have the same bounds and hence the same length.

References: access type, access type definition, access value, actual parameter, allocator, array bound, array component, array type, array type definition, bound of a range, compatible, component declaration, constant, constrained array definition, constrained array subtype, conversion, designate, designated type, discrete range, entry, entry family declaration, expression, formal parameter, function, generic actual parameter, generic formal parameter, and 12.3, generic parameter, index, index constraint, index subtype, initial value, integer literal, integer type, iteration rule, mode, name, null range, object, type, range, record component, renaming declaration, result subtype, satisfy, subprogram, subtype conversion, subtype indication, type mark, unconstrained array type, unconstrained subtype, universal type, universal_integer type, variable.

Style Guide references: 5.5.2 Array Attributes, 9.1.3 Arrays

3.6.2. Operations of Array Types


The basic operations of an array type include the operations involved in assignment and aggregates (unless the array type is limited), membership tests, indexed components, qualification, and explicit conversion; for one-dimensional arrays the basic operations also include the operations involved in slices, and also string literals if the component type is a character type.

If A is an array object, an array value, or a constrained array subtype, the basic operations also include the attributes listed below. These attributes are not allowed for an unconstrained array type. The argument N used in the attribute designators for the N-th dimension of an array must be a static expression of type universal_integer. The value of N must be positive (nonzero) and no greater than the dimensionality of the array.

In addition, the attribute T'BASE is defined for an array type or subtype T (see 3.3.3); the attribute T'SIZE is defined for an array type or subtype T, and the attributes A'SIZE and A'ADDRESS are defined for an array object A (see 13.7.2).

Besides the basic operations, the operations of an array type include the predefined comparison for equality and inequality, unless the array type is limited. For one-dimensional arrays, the operations include catenation, unless the array type is limited; if the component type is a discrete type, the operations also include all predefined relational operators; if the component type is a boolean type, then the operations also include the unary logical negation operator not, and the logical operators.

Examples (using arrays declared in the examples of section 3.6.1):

--  FILTER'FIRST       =    0   FILTER'LAST        =  31   FILTER'LENGTH  =  32
--  RECTANGLE'LAST(1)  =   20   RECTANGLE'LAST(2)  =  30


The attributes A'FIRST and A'FIRST(1) yield the same value. A similar relation exists for the attributes A'LAST, A'RANGE, and A'LENGTH. The following relations are satisfied (except for a null array) by the above attributes if the index type is an integer type:

    A'LENGTH    = A'LAST    - A'FIRST    + 1
    A'LENGTH(N) = A'LAST(N) - A'FIRST(N) + 1 

An array type is limited if its component type is limited (see 7.4.4).

References: aggregate, array type, assignment, attribute, basic operation, bound of a range, catenation operator, and 4.5.3, character type, constrained array subtype, conversion, designator, dimension, index, indexed component, limited type, logical operator, and 4.5.1, membership test, and 4.5.2, not operator, and 4.5.6, null range, object, operation, predefined operator, qualified expression, relational operator, and 4.5.2, slice, static expression, string literal, subcomponent, type, unconstrained array type, universal type, universal_integer type.

Style Guide references: 5.6.2 Slices

3.6.3. The Type String


The values of the predefined type STRING are one-dimensional arrays of the predefined type CHARACTER, indexed by values of the predefined subtype POSITIVE:

    subtype POSITIVE is INTEGER range 1 .. INTEGER'LAST;
    type STRING is array(POSITIVE range <>) of CHARACTER; 


    STARS      : STRING(1 .. 120) := (1 .. 120 => '*' );
    --  QUESTION'FIRST = 1, QUESTION'LAST = 20 (the number of characters)    

    NINETY_SIX : constant ROMAN   := "XCVI";        --  see 3.6 


String literals (see 2.6 and 4.2) are basic operations applicable to the type STRING and to any other one-dimensional array type whose component type is a character type. The catenation operator is a predefined operator for the type STRING and for one-dimensional array types; it is represented as &. The relational operators <, <=, >, and >= are defined for values of these types, and correspond to lexicographic order (see 4.5.2).

References: aggregate, array, catenation operator, and 4.5.3, character type, component type (of an array), dimension, index, lexicographic order, positional aggregate, type, relational operator, and 4.5.2, string literal, subtype, type.

Style Guide references: 2.1.1 Horizontal Spacing


[Ada Information Clearinghouse]

Address any questions or comments to