За пределами массива
Что происходит, если использовать индекс, которому не соответствует ни один элемент, например индекс 5 в массиве из пяти элементов? Это зависит от того, чем является индекс: числом, записанным в коде, или переменной.
Если индекс — число, компилятор видит ошибку, и программа не компилируется:
#include <stdio.h>
int main(void) {
int scores[5] = {80, 92, 75, 60, 88};
printf("%d\n", scores[5]);
return 0;
}main.c:5:20: error: array index 5 is past the end of the array (that has type 'int[5]') [-Werror,-Warray-bounds]
5 | printf("%d\n", scores[5]);
| ^ ~
main.c:4:5: note: array 'scores' declared here
4 | int scores[5] = {80, 92, 75, 60, 88};
| ^
1 error generated.В сообщении сказано, что индекс 5 находится за концом массива, тип которого int[5]: массив из пяти int. Строки ниже, начинающиеся с note:, показывают, где массив был создан. Отрицательный индекс — тоже ошибка: для scores[-1] в сообщении сказано, что индекс -1 находится перед началом массива.
Если индекс — переменная, компилятор его не проверяет, потому что переменная получает значения только во время работы программы. Вот что происходит, когда цикл делает один шаг лишний, с <= вместо <:
#include <stdio.h>
int main(void) {
int scores[5] = {80, 92, 75, 60, 88};
for (int i = 0; i <= 5; i++) {
printf("%d\n", scores[i]);
}
printf("Готово\n");
return 0;
}80
92
75
60
88
RuntimeError: unreachableПрограмма выводит все пять элементов. В шестой итерации цикла i равно 5, и на scores[5] программа останавливается с красной ошибкой RuntimeError: unreachable. Слово Готово так и не выводится. Сообщение не говорит, что именно пошло не так, но в этом уроке оно означает индекс за пределами массива. Последняя выведенная строка показывает, докуда дошла программа.
То же происходит, когда число повторений цикла больше размера массива, например const int COUNT = 6; для массива из пяти элементов.
Почему это так важно? Сам C индексы вообще не проверяет. Обычная программа на C на вашем компьютере прочитала бы то, что лежит в памяти после массива, возможно, другую переменную, и продолжила бы работу с неверным значением. Запись в scores[5] могла бы даже перезаписать другую переменную. Такая программа может казаться работающей и всё же давать неверные результаты, а найти ошибку очень трудно. Здесь программа останавливается на таком индексе, чтобы вы сразу увидели ошибку. Но лучшая защита — правильно выбирать индексы: у первого элемента индекс 0, у последнего — размер − 1, а в условии цикла по массиву стоит i < COUNT.
Задание
- 1
Программа должна вывести время четырёх кругов. Запустите её: она выводит три круга и останавливается с
RuntimeError: unreachable. В последней итерации циклаiравно4, аlaps[4]находится за концом массива. Исправьте условие цикла так, чтобы цикл заканчивался до того, какiдостигнет4. Тогда в конце программа выведетФиниш. - 2
Теперь программа доходит до конца, но первого круга нет:
Круг 1показывает58, время второго круга. Сделайте так, чтобы цикл начинался с индекса0, а номер круга выводился какi + 1. Тогда вывод будет таким:Круг 1: 62 с Круг 2: 58 с Круг 3: 60 с Круг 4: 57 с Финиш