Yes constants can be used along with any expression that evaluates to an appropriate and valid index for the array. You should also note that an array in Delphi could be declared with a non-zero based index range:
var
MonthlyTotals: array[1..12] of Integer; // Jan = 1, Feb = 2 etc etc
You can even specify the index of an array as an enum type and use enum members for the indices which provides even tighter safety (where possible and appropriate), as per this contrived example:
type
TFileFormat = (ffXML, ffCSV, ffText, ffJSON);
var
sExtensions: array[TFileFormat] of String;
sExtensions[ffXML] := 'xml';
sExtensions[ffCSV] := 'csv';
sExtensions[ffText] := 'txt';
sExtensions[ffJSON] := 'json';
In such cases the array might only have members for certain (contiguous) values in the enum:
var
sExtensions: array[ffXML..ffCSV] of String;
For this reason, and the fact that array indices may not be zero based, unless you are 110% certain of the index range of an array it is a good idea to always use Low() and High() to determine the index bounds when iterating over the contents of an array and not assume the index basis:
// This will not work properly:
for i := 0 to 11 do
MonthlyTotals[i] := ....
// Neither will this, even though it looks more safe
for i := 0 to Pred(Length(MonthlyTotals)) do
MonthlyTotals[i] := ....
// This will be safe:
for i := Low(MonthlyTotals) to High(MonthlyTotals) do
MonthlyTotals[i] := ....
// And it works for enum indices as well:
for ext := Low(sExtensions) to High(sExtensions) do
sExtensions[ext] := ....