Ранее уже указывалось, что при старте программы всем переменным (простым и составным), перечисленным в разделе Var, выделяется память, размер которой зависит от типа переменной. Поля памяти выделяются в порядке перечисления переменных в разделе Var. В данном случае имеем
1 2 3 599 600 601 602 603 604 605 606
. . .
½¾¾¾¾¾¾¾ X ¾¾¾¾¾¾®½ n ®½ i ® ½ k ®½
На рисунке байты, входящие в состав полей X, n, i и k, пронумерованы последовательно. Условно можно считать, что номер байта - это его адрес в памяти.
Адрес произвольного элемента в машинной программе вычисляется следующим образом:
Addr( ) = X + ( i - 1 ) × SizeOf(real) ,
где X - адрес поля X (адрес его крайнего левого байта),
SizeOf(real) - размер поля памяти типа real.
Рассмотрим два варианта фрагмента программы:
1. n:=100; k:=500;
x[101]:=5;
Writeln('n= ',n,' k= ',k);
2. n:=100; k:=500;
i:=101; x[i]:=5;
Writeln('n= ',n,' k= ',k);
В приведенном выше описании индекс массива имеет диапазонный тип При трансляции для индекса массива отводится некоторое поле памяти и указывается тип переменной, которая размещается в этом поле (в данном случае диапазонный тип Diap). Придадим условно этой переменной имя Ind. Тогда выражения x[i], x[k], x[n] означают, что переменной Ind присваиваются соответственно значения i, k или n, т.е. имеет место присваивание ординальной переменной нового значения.
В вариантах 1 и 2 числовое значение 5 должно записываться в поле памяти, соответствующее адресу 101-го элемента массива X, т.е. в байты 601 .. 606. При этом значения переменных n, i и k будут испорчены, что в дальнейшем может привести к непредсказуемым последствиям при работе программы.
Указанную выше ошибку, которая заключается в том, что индекс элемента массива принимает значение вне допустимого диапазона 1 .. Nmax, называют выходом за границы массива.
Для оператора x[101] := 5 информация о том, что индекс элемента массива имеет недопустимое значение, известна по исходному тексту программы, в связи с чем данная ошибка определяется на этапе трансляции. При этом на экран выводится сообщение
Error 76 Const out of range
( Константа нарушает границы )
Аналогичная ошибка для оператора x[i] := 5 в варианте 2 не может быть обнаружена при трансляции программы, поскольку конкретное значение переменной i становится известным лишь при работе программы. В частности, при отработке второго варианта фрагмента программы оператор Writeln('n= ',n,' k=',k); выдаст на печать значения
n = 131 k = 8192.
Примечание. Значение числа 5 в формате real на машинном уровне имеет вид 200000000083. Здесь первые два байта воспринимаются как значение переменной k: 200016= 819210; следующие два байта – переменной i, последние два байта – переменной n: 8316=13110.
Для индикации ошибки выхода за границы массива при работе программы используют директиву компилятора R (от слова Range - граница). При включенной директиве R компилятор записывает в машинную программу дополнительные команды, которые проверяют корректность присваивания новых значений всем ординальным переменным, в том числе и индексам массивов. При обнаружении некорректного присваивания работа программы прерывается, а на экран выдается сообщение
Error 201 Range check error
( Ошибка при проверке границ )
Индекс элемента массива может быть лишь ординального типа. Его допустимые значения определяются описанием типа массива. В приведенном выше примере индекс элемента массива X может принимать значения лишь в диапазоне от 1 до 100. Следовательно, при выходе индекса массива за допустимые границы и включенной директиве R будет также сгенерировано прерывание программы с выводом сообщения об ошибке 201.
Пусть мы имеем описание
Var k,l : byte;
m,n : integer;
p,q : 1..5000;
и два фрагмента программы:
1. k:=400; l:=-1;
p:=0; q:=6000;
2. m:=400; n:=-1;
k:=m; l:=n;
m:=0; n:=6000;
p:=m; q:=n.
Ошибка присваивания переменным k, l, p и q недопустимых значений в фрагменте 1 обнаруживается на этапе трансляции, в фрагменте 2 - при работе программы, если включена директива R (пример использования директивы R показан в следующем разделе).
При включенной директиве R за счет добавления в программу дополнительных машинных команд увеличиваются объем программы и время ее выполнения. Поэтому директиву R рекомендуется использовать только при отладке программы, а после окончания отладки удалять ее из состава программы.