Ada: Arrays
An Ada array is a collection of elements of one type, indexed by any discrete type — not just integers starting at zero. Arrays are bounds-checked, can be indexed by enumerations, and know their own dimensions through attributes. Indexing errors simply cannot hide.
Constrained Arrays
A constrained array fixes its index range at declaration. Index ranges are yours to choose: 0 .. 9, 1 .. 10, even -5 .. 5:
with Ada.Text_IO; use Ada.Text_IO;
procedure Array_Demo is
type Temperatures is array (1 .. 7) of Float; -- days of a week
type Bit_Row is array (0 .. 7) of Boolean; -- byte-like indexing
Week : Temperatures := (21.5, 22.0, 19.8, 20.1, 23.4, 24.0, 18.9);
begin
Week (3) := 20.5; -- index, not pointer arithmetic
-- Week (8) := 0.0; -- compile error: 8 not in 1 .. 7
Put_Line (Float'Image (Week (3))); -- 20.5
Put_Line (Integer'Image (Week'Length)); -- 7 — the array knows its size
end Array_Demo;
Aggregates initialize several elements at once — with named or ranged choices for clarity:
type Grid is array (1 .. 3, 1 .. 3) of Integer; -- 2-D, rectangular
Board : constant Grid := (others => (others => 0)); -- every element 0
Row3 : constant Bit_Row := (0 .. 5 => False, 6 | 7 => True);
Unconstrained Arrays
Declare the type of indices without fixing them, then fix them per object. String is exactly this — an unconstrained array of Character:
procedure Vector_Demo is
type Int_Vector is array (Positive range <>) of Integer; -- bounds open
A : Int_Vector (1 .. 4) := (1, 2, 3, 4); -- bounds chosen here
B : Int_Vector (10 .. 13) := (10, 11, 12, 13); -- non-zero base is normal
begin
-- A := B; -- legal! same element type and length; bounds are copied
null;
end Vector_Demo;
Whole-array assignment copies all elements — no memcpy, and a length mismatch is a run-time check that raises Constraint_Error instead of corrupting memory.
Slices
A slice names a contiguous run of elements and behaves like an array of that length. Slices read and write:
procedure Slice_Demo is
type Int_Vector is array (Positive range <>) of Integer;
V : Int_Vector (1 .. 8) := (1, 2, 3, 4, 5, 6, 7, 8);
begin
V (6 .. 8) := V (1 .. 3); -- copy elements 1..3 onto 6..8: 1,2,3,4,5,1,2,3
V (1 .. 2) := (0, 0); -- overwrite a range with an aggregate
null;
end Slice_Demo;
Enumerated Index Types
Because any discrete type can index, arrays keyed by domain values need no hashing and no lookup tables:
procedure Sensor_Demo is
type Sensor is (Left, Center, Right);
type Readings is array (Sensor) of Float; -- indexed BY the enum
R : Readings := (Left => 0.5, Center => 0.7, Right => 0.2);
begin
for S in Sensor'Range loop
null; -- iterate the three sensors — all of them, by name
end loop;
end Sensor_Demo;
The compiler checks that every Sensor value has a slot. Missing one in an aggregate is an error — the array cannot go out of sync with its index type.
Attributes You Will Use Daily
| Attribute | Meaning | Replaces (C habits) |
|---|---|---|
A'First / A'Last | lowest / highest valid index | sizeof arithmetic |
A'Length | number of elements | sizeof(a)/sizeof(a[0]) |
A'Range | the whole index range for loops | hand-copied loop bounds |
Out-of-range indexing raises Constraint_Error at the exact line — never a silent overrun. Next: Records.