Программирование >>  Дополнительные возможности наследования 

1 ... 103 104 105 [ 106 ] 107 108 109 ... 265


предупреждение

Ни в коем случае не запускайте эту программу у себя на компьютере. Она может привести к поломке системы.

Аисшииг 12.Z. Запись зг ирадиды массиап

2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

Листинг 12.2.

Пример того, что может произойти при записи за пределы массива

Sinclude <iostream.h>.

int main()

часовые

long sentinel0ne[3];

long TargetArray[25]; массив для записи данных

long sentinelTwo[3];

int i;

for (i=0; i<3; i++) sentinelOne[i] = sentinelTwo[i] = 0;

for (i=0; i<25; i++) TargetArray[i] = 0;

cout Test 1: \ n ; cout TargetArrayfO]; cout TargetArray[24]:

test current values (should be TargetArray[0] \ n ; TargetArray[24] \ n\ n

for (i = 0; i<3; i++) {

cout sentinelOne[ i cout sentinelOne[i] \ n cout sentinelTwo[ i cout sentinelTwo[i] \ n

cout \ nAssigning.,. ; for (1 = 0; i<=25; i++) TargetArray[i] = 20;

cout \ nTest 2; \ n ; cout TargetArray[0]; cout TargetArray[24]; cout TargatArray[25]: for (i = 0; i<3; {

cout sentinelOne[ i cout sentinilOne[l]<< \ n ; eout sentinelTwo[ 1 ]:

TargetArray[0] \ n ; TargetArray[24] \ n ; TargetArrayi25] Л n\ n



44 45 46 47 48

cout << sentinelTwo[i] \ n

return 0;

Test 1;

TargetArray[0]

TargetArray[24]: 0

SentinelOne[0]

SentinelTwo[0]

SentinelOne[1]

SentinelTwo[1]

Sentiriel0ne[2]

SentinelTwo[2]

Assigning. . .

Test 2:

TargetArray[0]

TargetArray[24]: 20

TargetArray[25]: 20

SentinelOne[0]

SentinelTwo[0]

Sentinel0ne[1]

SentinelTwo[1]

Sentinel0ne[2]

SentinelTwo[2]

в строках 9 и 11 объявляются два массива типа long по три элемента в каж-

дом, которые выполняют роль часовых вокруг массива TargetArray. Изначально значения этих массивов устанавливаются в 0. Если будет записано значение в массив TargetArray по адресу, выходящему за пределы этого массива, то значения массивов-часовых изменятся. Одни компиляторы ведут отсчет по возрастающей от адреса массива, другие - по убывающей. Именно поэтому используется два вспомогательных массива, расположенных по обе стороны от целевого массива TargetArray.

В строках 19-29 проверяется равенство нулю значений элементов массивов-часовых (Test 1). В строке 33 элементу массива TargetArray присваивается значение 20, но при этом указан индекс 25, которому не соответствует ни один элемент массива TargetArray.

В строках 36-38 выводятся значения элементов массива TargetArray (Test 2). Обратите внимание, что обращение к элементу массива TargetArray[25] проходит вполне успешно и возвращается присвоенное ранее значение 20. Но когда на экран выводятся значения массивов-часовых SentinelOna и SentinelTwo, вдруг обнаруживается, что значение элемента массива SentlnelOne изменилось. Дело в том, что обращение к массиву TargetArray[25] ссылается на ту же ячейку памяти, что и элемент массива Sent1nelOne[0]. Таким образом, записывая значения в несуществующий элемент массива TargetArray, профамма изменяет значение элемента совсем другого массива.



Если далее в протрамме значения элементов массива SentinelOne будут использоваться в каких-то расчетах, то причину возникновения ошибки будет сложно определить. В этом состоит коварство ввода значений за пределы массива.

В нашем примере размеры массивов были заданы значениями 3 и 25 в объявлении массивов. Гораздо безопаснее использовать для этого константы, объявленные где-нибудь в одном месте программы, чтобы профаммист мог легко конфолировать размеры всех массивов в профамме.

Еше раз отметим, что, поскольку разные компиляторы по-разному ведут отсчет адресов памяти, результат выполнения показанной выше программы может отличаться на вашем компьютере.

ОшиОки подсчета столОое для заОора

Ошибки с записью данных за пределы массива случаются настолько часто, что для них используется особый термин - ошибки подсчета столбов для забора. Такое сфан-ное название было придумано по аналогии с одной житейской проблемой - подсчетом, сколько столбов нужно вкопать, чтобы установить 10-метровый забор, если расстояние между столбами должно быть 1 м. Многие не задумываясь отвечают - десять. Вот если бы задумались и посчитали, то нашли бы правильный ответ - одиннадцать. Если вы не поняли почему, посмотрите на рис. 12.2.

Ошибка на единицу при установке индекса в обращении к массиву может стоить профамме жизни. Нужно время, чтобы начинающий профаммист привык, что при обращении к массиву, состоящему из 25 элементов, индекс не может превышать значение 24 и отсчет начинается с О, а не с 1. (Некоторые профаммисты потом настолько к этому привыкают, что в лифте нажимают на кнопку 4, когда им нужно подняться на пятый этаж.)


ОРИМЕЧАНИЕ

Иногда элемент массива ИмяМассива[0] называют нулевым, а не первым. Но и в этом случае легко запутаться. Если элемент ИмяМассива[0] нулевой, то каким тогда будет элемент ИмяМассива[т.]7 Первым или вторым? И так далее... Каким будет элемент ИмяМассива[2А]- двадцать четвертым или двадцать пятым? Правильно будет считать элемент ИмяМассиваЮ] первым, имеющим нулевой сдвиг.

Инициализация массива

Инициализацию массива базового типа (например, int или char) можно проводить одновременно с его объявлением. Для этого за выражением объявления массива нужно установить знак равенства (=) и в фигурных скобках список значений элементов массива, разделенных запятыми. Например:

int IntegerArray[5] = {10, 20, 30, 40, 50};

В этом примере объявляется массив целых чисел IntegerArray и элементу IntegerArray[0] присваивается значение 10, элементу IntegerArray[ 1 ] - 20 и т.д.

Если вы опустите установку размера массива, то компилятор автоматически вычислит размер массива по списку значений элементов. Поэтому справедливой является следующая запись:

int IntegerArray[] = {10. 20. 30, 40, 50};



1 ... 103 104 105 [ 106 ] 107 108 109 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика