Вы не переопределяете существующую переменную, вы определяете новую переменную.
Рассмотрим этот пример:
#include <stdio.h>
int main(void) {
int x = 42;
printf("Outside, start. x (%p) = %d\n", (void *)&x, x);
{
printf("Inner block, start. x (%p) = %d\n", (void *)&x, x);
int x = 123;
printf("Inner block, end. x (%p) = %d\n", (void *)&x, x);
}
printf("Outside, end. x (%p) = %d\n", (void *)&x, x);
return 0;
}
Пример вывода:
Outside, start. x (0x7ffd6e6b8abc) = 42
Inner block, start. x (0x7ffd6e6b8abc) = 42
Inner block, end. x (0x7ffd6e6b8ab8) = 123
Outside, end. x (0x7ffd6e6b8abc) = 42
[ Демонстрационная версия ]
Эта программа выводит адрес памяти и значение x
. Большинство случаев использования x
относятся к внешней переменной, объявленной в начале main. Но во внутреннем блоке после int x = 123;
все вхождения x
относятся ко второй отдельной переменной, которая также называется x
(но в остальном независима).
Когда выполнение покидает внутренний блок, внешняя переменная x
снова становится видимой.
Это также называется shadowing .
В вашем коде внешний len
никогда не изменяется, поэтому while(len > 1)
всегда имеет значение.
Кстати, теневое копирование является очень распространенной концепцией в большинстве языков, которые поддерживают блочную область видимости: