Craig
Craig

Reputation: 13

Ada array aggregate initialization

I am trying to initialize a simple Ada array using an aggregate, and I would like the compiler to determine the array bounds. However, When trying to use Test_2 below, I cannot simply use integer subscripts. Is there a way to allow the compiler to determine the array bounds arrays, and yet access them using the simple "Test_2(0)" notation?

I am using gnat.

Thanks.

with Interfaces;                   use Interfaces;

procedure Test_Init is
   type U16_a is array(Integer range <>) of Unsigned_16;

   -- array aggregate initialization
   Test_1 : U16_a(0..1) := (16#1234#, 16#5678#); -- ok, but...
   Test_2 : U16_a       := (16#8765#, 16#4321#); -- let compiler create bounds

   Test_3 : Unsigned_16;
begin

    -- Test_1 obviously works
    Test_3 := Test_1(0);

    -- warning: value not in range of subtype of "Standard.Integer" defined at line 8
    -- This produces a constraint.
    -- What is the subtype that is defined at line 8?  It is not Integer (0..1)
    Test_3 := Test_2(0);

    -- this works though
    Test_3 := Test_2(Test_2'First);

    -- and this works
    Test_3 := Test_2(Test_2'Last);

    -- and this works
    Test_3 := Test_2(Test_2'First + 1);

end Test_Init;

Upvotes: 1

Views: 1334

Answers (1)

Keith Thompson
Keith Thompson

Reputation: 263267

If you don't specify the bounds, the lower bound of the array is the lower bound of the index type. (You may be accustomed to languages like C, where arrays always have a lower bound of 0. That's not the case in Ada.)

In this case, the lower bounds is Integer'First, which is probably -2147483648.

If you want the array bounds to start at 0, you can use the subtype Natural:

type U16_a is array(Natural range <>) of Unsigned_16;

Or you can use the subtype Positive to set the array's lower bound to 1.

You can also specify the index of each element:

Test_2 : U16_a       := (0 => 16#8765#, 1 => 16#4321#);

but that may not scale as well; if there are a large number of elements, you have to specify the index for each one, since positional associations can't follow named associations.

Instead of using positional or named aggregate initializers you can use array concatenation to specify the first index:

Test_3 : U16_a := (0 => 0) & (1, 2, 3, 4, 5, 6, 7);

The reference manual states:

If the ultimate ancestor of the array type was defined by an unconstrained_array_definition, then the lower bound of the result is that of the left operand.

It's cleaner to pick an index subtype with the desired lower bound.

Upvotes: 7

Related Questions