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

AttributeMeaningReplaces (C habits)
A'First / A'Lastlowest / highest valid indexsizeof arithmetic
A'Lengthnumber of elementssizeof(a)/sizeof(a[0])
A'Rangethe whole index range for loopshand-copied loop bounds

Out-of-range indexing raises Constraint_Error at the exact line — never a silent overrun. Next: Records.