Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Turbo Pascal / Stud_1_1 / LecRus / MainPart.doc
Скачиваний:
117
Добавлен:
03.03.2016
Размер:
5.03 Mб
Скачать

6. Начальное и конечное значения параметра цикла вычисляются только один раз, до начала цикла.

Следовательно, изменение выражений 1 или 2 в теле цикла никакого влияния на его работу не оказывает.

Вариант предыдущего примера (фрагмент):

k:=0;

For i:=1 to n do

If x[i]< 0 then

Begin

k:=i; n:=0

End;

Здесь будет найден не первый, а последний отрицательный элемент. Кроме того, будет «испорчена» переменная n, определяющая текущий размер массива.

7. При нормальном завершении цикла значение его параметра считается неопределенным.

Способ реализации оператора For зависит от системы машинных команд конкретного типа ЭВМ. В зависимости от способа реализации параметр цикла i после завершения работы оператора

For i:=1 to n do

S:=S+x[i];

может иметь значение или n, или n+1. Поэтому использовать конечное значение параметра цикла при нормальном (не принудительном) его завершении не рекомендуется, поскольку это может привести к получению неправильных результатов.

Пример некорректного использования параметра цикла:

For i:=1 to n do

S:=S+x[i];

k:=i+1;

Контроль ординальных переменных

Пусть мы имеем следующее описание:

Const Nmax = 100;

Type Diap = 1..Nmax;

Ar = array[Diap] of real;

Var X : Ar;

n,i,k : integer;

Ранее уже указывалось, что при старте программы всем переменным (простым и составным), перечисленным в разделе 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 рекомендуется использовать только при отладке программы, а после окончания отладки удалять ее из состава программы.

Соседние файлы в папке LecRus