Циклы: for, while, do-while
Урок разбирает три цикла C — for, while и do-while, их внутреннее устройство, управление через break и continue и самые частые ошибки: бесконечный цикл и ошибку на единицу.
Цикл for в C — это не «перебор элементов», а три самостоятельные части: инициализация, условие и шаг. Понимание этой тройки объясняет всё поведение цикла.
Самый частый цикл — for. Его заголовок состоит из трёх частей, разделённых точкой с запятой:
for (int i = 0; i < 5; i++) {
printf("%d ", i); // 0 1 2 3 4
}
Первая часть (int i = 0) выполняется один раз в начале. Вторая (i < 5) проверяется перед каждым проходом — пока истинна, цикл работает. Третья (i++) выполняется после каждого прохода. Цикл while проще — только условие:
int i = 0;
while (i < 5) {
printf("%d ", i);
i++;
}
Цикл do-while проверяет условие В КОНЦЕ, поэтому тело выполняется хотя бы раз — это удобно для меню и повторного ввода:
int n;
do {
printf("Введите положительное число: ");
scanf("%d", &n);
} while (n <= 0);
Как работает под капотом
Покажем порядок выполнения частей for наглядно — это снимает почти все вопросы о циклах:
for (i = 0; i < 3; i++) { тело; }
[1] i = 0 (один раз, в самом начале)
|
v
[2] i < 3 ? --НЕТ--> выход из цикла
| ДА
v
[3] тело цикла
|
v
[4] i++ (шаг)
|
+----> назад к [2]
Порядок: 1 -> 2 -> 3 -> 4 -> 2 -> 3 -> 4 -> ... -> 2(нет) -> выход
Операторы break и continue управляют ходом цикла: break немедленно выходит из цикла целиком, continue пропускает остаток тела и переходит к следующей итерации (включая шаг и проверку).
Частые ошибки
- Бесконечный цикл. Если забыть менять переменную (
i++) или условие никогда не становится ложным — программа зависает.while (1)безbreakвнутри — тоже навсегда. - Ошибка на единицу (off-by-one).
i <= nвместоi < nделает на один проход больше — и выходит за границу массива. - Точка с запятой после for.
for (...);создаёт цикл с пустым телом, а следующий блок выполнится один раз. - Изменение счётчика внутри for и в шаге одновременно — легко потерять контроль над количеством итераций.
Best practices
- Используйте
for, когда число итераций известно заранее, иwhile, когда выход зависит от условия. - Объявляйте счётчик прямо в for:
for (int i = 0; ...)— переменная не «утечёт» наружу и не помешает другому коду. - Граница — почти всегда
i < n, а неi <= n. Эта привычка спасает от выхода за пределы массива.
Все три вида циклов есть и в Python, поэтому логику разных границ удобно проверить там. Заметьте классическую ошибку off-by-one.
# Сравним правильную и ошибочную границу цикла
arr = [10, 20, 30, 40, 50] # 5 элементов, индексы 0..4
print("Правильно (i < len):")
for i in range(len(arr)): # как for(i=0; i<5; i++) в C
print(" ", arr[i])
print("Сумма через while:")
s, i = 0, 0
while i < len(arr):
s += arr[i]
i += 1
print(" итого:", s)
Та же логика на Python ▶ — в C обращение arr[5] при индексах 0..4 не вызовет ошибку, а молча прочитает чужую память. Поэтому граница i < len критична.
Цена итерации и кэш процессора
Циклы — это не только логика, но и производительность, и в C она видна особенно ясно. Современный процессор читает память не по одному байту, а блоками (кэш-линиями), поэтому обход данных подряд, в порядке их расположения в памяти, в разы быстрее, чем «прыжки» по случайным адресам. Для массива это означает: проход for (i = 0; i < n; i++) по соседним элементам максимально дружелюбен к кэшу. Когда мы дойдём до двумерных массивов, вы увидите, что порядок вложенных циклов влияет на скорость именно по этой причине. В высокоуровневых языках такие детали скрыты, а в C вы управляете ими напрямую — и потому C остаётся выбором там, где важна каждая микросекунда: в обработке сигналов, графике, играх и научных расчётах.
Итоги
В C три цикла: for (три части: инициализация, условие, шаг), while (только условие, проверка в начале) и do-while (проверка в конце, тело хотя бы раз). Управление — через break и continue. Главные ошибки — бесконечный цикл и off-by-one; защита — менять счётчик аккуратно и использовать границу i < n.