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 component_subtype_indication

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:

- The array type is an implicitly declared anonymous type; this type is defined by an (implicit) unconstrained array definition, in which the component subtype indication is that of the constrained array definition, and in which the type mark of each index subtype definition denotes the subtype defined by the corresponding discrete range.

- The array subtype is the subtype obtained by imposition of the index constraint on the array 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

Note:

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

**Sub-topics:**

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 a variable declared by an object declaration, the subtype indication of the corresponding object declaration must define a constrained array subtype (and, thereby, the bounds). The same requirement exists for the subtype indication of a component declaration, if the type of the record component is an array type; and for the component subtype indication of an array type definition, if the type of the array components is itself an array type.
- For a constant declared by an object declaration, the bounds of the constant are defined by the initial value if the subtype of the constant is unconstrained; they are otherwise defined by this subtype (in the latter case, the initial value is the result of an implicit subtype conversion). The same rule applies to a generic formal parameter of mode in.
- For an array object designated by an access value, the bounds must be defined by the allocator that creates the array object. (The allocated object is constrained with the corresponding values of the bounds.)
- For a formal parameter of a subprogram or entry, the bounds are obtained from the corresponding actual parameter. (The formal parameter is constrained with the corresponding values of the bounds.)
- For a renaming declaration and for a generic formal parameter of mode in out, the bounds are those of the renamed object or of the corresponding generic actual parameter.

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 bounds

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

type VAR_LINE(LENGTH : INTEGER) is record IMAGE : STRING(1 .. LENGTH); end record; NULL_LINE : VAR_LINE(0); -- NULL_LINE.IMAGE is a null array

Notes:

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

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.

- A'FIRST Yields the lower bound of the first index range. The value of this attribute has the same type as this lower bound.
- A'FIRST(N) Yields the lower bound of the N-th index range. The value of this attribute has the same type as this lower bound.
- A'LAST Yields the upper bound of the first index range. The value of this attribute has the same type as this upper bound.
- A'LAST(N) Yields the upper bound of the N-th index range. The value of this attribute has the same type as this upper bound.
- A'RANGE Yields the first index range, that is, the range A'FIRST .. A'LAST.
- A'RANGE(N) Yields the N-th index range, that is, the range A'FIRST(N) .. A'LAST(N).
- A'LENGTH Yields the number of values of the first index range (zero for a null range). The value of this attribute is of the type universal_integer.
- A'LENGTH(N) Yields the number of values of the N-th index range (zero for a null range). The value of this attribute is of the type universal_integer.

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

Notes:

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

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;

Examples:

STARS : STRING(1 .. 120) := (1 .. 120 => '*' ); QUESTION : constant STRING := "HOW MANY CHARACTERS?"; -- QUESTION'FIRST = 1, QUESTION'LAST = 20 (the number of characters) ASK_TWICE : constant STRING := QUESTION & QUESTION; NINETY_SIX : constant ROMAN := "XCVI"; -- see 3.6

Notes:

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

Address any questions or comments to adainfo@sw-eng.falls-church.va.us.