БЕСПЛАТНАЯ ПОДГОТОВКА К ЕГЭ ПО ПРОФИЛЬНОЙ МАТЕМАТИКЕ
Подготовься к ЕГЭ-2026 по профильной математике самостоятельно с помощью сервиса "1С:Репетитор"!
Понятная теория и эффективные тренажеры с объяснением! Вы успеете подготовиться к экзамену! Начните занятия прямо сейчас!
design_arrow

Локальные переменные

Локальная переменная – это именованное хранилище данных, объявленное внутри блока/функции и доступное только в пределах области видимости этого блока. Тема объединяет три фундаментальных понятия: область видимости (scope), время жизни (lifetime) и место хранения (storage). Для ЕГЭ по информатике понимание локальных переменных критично в задачах на функции/процедуры, рекурсию, замыкания, корректную работу со счётчиками циклов, а также при анализе программ, где требуется предсказать значение переменных после выполнения фрагмента.

Понятийный аппарат (точные определения)

  • Область видимости (scope) – множество точек программы, в которых имя переменной доступно для использования. Для лексически-скоупируемых языков (Pascal, C/C++, Python) это лексический блок: функция, тело цикла, begin…end, отступ в Python.

  • Время жизни (lifetime) – интервал исполнения, когда значение переменной существует в памяти.

  • Место хранения (storage) – где физически лежит значение (обычно стек активаций; реже – статическая область или куча при захвате в замыкание).

  • Теневание (shadowing) – локальное имя «перекрывает» одноимённую переменную внешнего уровня.

  • Активирующая запись (activation record, кадр стека) – набор локальных переменных, параметров и служебной информации вызова функции.

Формально, для переменной x, объявленной внутри блока B, верно:

  • доступность: x видна, если текущая точка исполнения ∈ scope(B) и имя x не затенено именем из вложенного блока;

  • время жизни: [t_alloc(x), t_free(x)) ⊆ интервал исполнения B.

Модель выполнения: стек и кадры активаций

При вызове функции создаётся кадр стека с локальными переменными и параметрами. По завершении – кадр снимается, локальные переменные уничтожаются.

Классическая оценка памяти при рекурсии:

stack_usage = frame_size * recursion_depth

где frame_size – суммарный объём локалов и служебных полей, recursion_depth – максимальная глубина стека.

Инварианты:

  • Локальная переменная недоступна вне своего кадра.

  • Ссылки на локальные переменные «после выхода» недействительны (за исключением корректно реализованных замыканий/копий).

Правила объявления, инициализации и область видимости

Правило 1 (минимальная область): объявляйте локальную переменную в максимально узком блоке, где она нужна. Это снижает риски ошибок и улучшает читаемость.

Правило 2 (полная инициализация): локальные переменные должны быть инициализированы до первого чтения. В C/C++ это требование безопасности; в Python/Паскале чтение неинициализированной переменной – логическая ошибка.

Правило 3 (безопасность имён): избегайте повторного использования имен внешних переменных (теневание). Если оно неизбежно, документируйте намерение.

Пример (Python, показ лексической области и инициализации):

def f(a):

    # локальная переменная s видна только в f

    s = 0

    for x in a:

        s += x

    return s

Локальные переменные и параметры: значение, ссылка, константность

  • Передача по значению создаёт локальную копию параметра (в C++ примитивы). Изменения копии не влияют на аргумент.

  • Передача по ссылке/указателю разрешает функции менять внешние данные (C++ T&, T*; Pascal var-параметры).

  • Python (модель ссылок): имена – ссылки на объекты; присваивание внутри функции делает имя локальным, если не объявлен global/nonlocal. Мутирование изменяемого объекта через локальную ссылку влияет на внешний объект, переназначение имени – нет.

Примеры (ограничения области в Python):

x = 10

def g():

    # x здесь локальна, так как присваивание создаёт локальное имя

    x = 5

    return x

# Чтобы изменить внешнюю x:

def h():

    global x

    x = 5

Локальные константы и неизменяемость

  • Локальная константа – имя, значение которого не меняется после инициализации (Pascal const, C++ const, Python – идиоматично ИМЯ_ЗАГЛАВНЫМИ).

  • Правило 4 (минимизация мутабельности): объявляйте локалы константными, когда это возможно – упрощает доказательство корректности и снижает число ошибок.


Статические локальные переменные

Статический локал хранит значение между вызовами функции, но остаётся невидимым вне её области.

  • В C++: static int counter = 0; внутри функции.

  • В Python аналог – хранить состояние в атрибуте функции или использовать замыкание/объект.

Правило 5 (реентерабельность): статический локал нарушает реентерабельность и потокобезопасность, если изменяется без синхронизации.

Замыкания и захват локальных переменных

Замыкание – функция, которая «захватывает» переменные из лексического окружения. Важны два варианта:

  • Захват по значению (копия) – безопасен по времени жизни.

  • Захват по ссылке – требует гарантий, что захваченная переменная живёт дольше замыкания.

Python (LEGB и nonlocal):

def make_adder(k):

    s = 0  # локальная переменная внешней функции

    def add(x):

        nonlocal s

        s += x

        return x + k, s

    return add

Здесь s – локальная для make_adder, но доступна add через nonlocal. Без nonlocal присваивание создало бы новую локальную s внутри add.

Правило 6 (escape-анализ): не допускайте «утечки» ссылок на локальные переменные вне времени их жизни (актуально для языков без безопасных замыканий).

Локальные переменные, рекурсия и оценка ресурсов

Для рекурсивной функции со средним размером кадра frame_size и глубиной D (макс.):

stack_usage = frame_size * D

Если локальные массивы велики, используйте динамическое выделение в куче (или статическую память) и аккуратно освобождайте ресурсы. Для ЕГЭ важно уметь оценить пределы: где возможен переполнение стека и как преобразовать решение в итеративное.

Локальные переменные и многопоточность

Локальные переменные по определению приватны для потока (в кадре стека конкретного потока). Опасность возникает при:

  • доступе к общим статическим/глобальным объектам из функции;

  • захвате общей структуры в замыкание.

Правило 7 (потокобезопасность): изменяемые локалы безопасны, пока они не ссылаются на общий объект. При наличии общих объектов – используйте синхронизацию.

Типичные ошибки и диагностика

  1. Чтение до инициализации (C/C++ неопределённое поведение; в Python – UnboundLocalError).

  2. Теневание имён (переменная внешнего уровня «исчезает» в блоке).

  3. Зависание на «устаревшей» ссылке после выхода из функции (указатели/ссылки в C/C++).

  4. Неправильный global/nonlocal в Python – неожиданное изменение внешнего состояния.

  5. Статические локалы + рекурсия/параллелизм – некорректные результаты.

Мини-шпаргалка правил

  • Объявляйте локальные переменные как можно ближе к месту использования.

  • Инициализируйте локалы немедленно при объявлении.

  • Предпочитайте локальные константы и иммутабельные структуры.

  • Избегайте теневания и глобальных эффектов без нужды.

  • Для рекурсии/глубоких вызовов оценивайте stack_usage формулой
    stack_usage = frame_size * recursion_depth.

  • В Python: помните про LEGB и ключевые слова global, nonlocal.

Связь с подготовкой к ЕГЭ

В заданиях ЕГЭ регулярно встречаются:

  • определение результата фрагмента с локальными/глобальными переменными;

  • анализ рекурсивных функций (в том числе вычисление количества вызовов и значения счётчиков);

  • задачи на функции-генераторы и замыкания (Python) с nonlocal;

  • перевод псевдокода с блочной структурой в выбранный язык (PascalABC.NET, C++, Python) с сохранением области видимости.

Пять упражнений 

Упражнение 1. Область видимости и теневание (Python)
Дан код:

x = 7

def f(a):

    x = a + 1

    def g(b):

        return x + b

    return g(3)

res1 = f(2)

def h():

    global x

    x = x + 5

h()

res2 = x

а) Укажите значения res1 и res2.
б) Объясните, какие x (глобальная/локальная) используются в каждой точке.
в) Перепишите f так, чтобы внутренняя функция модифицировала «внешнюю локальную» x (используйте nonlocal).

Упражнение 2. Рекурсия и локальные счетчики (Pascal/C++)
Пусть рекурсивная функция вычисляет сумму цифр числа и в каждом кадре создаёт локальный массив из 16 целых.
а) Выразите stack_usage через frame_size и глубину рекурсии D.
б) Оцените максимальную глубину для числа до 10^18.
в) Предложите итеративный вариант без рекурсии и сравните использование памяти.

Упражнение 3. Замыкание и nonlocal (Python)
Напишите функцию make_counter(start), возвращающую две функции: inc() (увеличивает счётчик и возвращает его) и reset() (сбрасывает к start).
а) Реализуйте корректный захват локальной переменной.
б) Покажите, почему без nonlocal поведение будет неверным.
в) Объясните, где и как живёт захваченная локальная переменная.

Упражнение 4. Статический локал и реентерабельность (C++/псевдокод)
Дана функция:

int f() {

    static int s = 0;

    s += 1;

    return s;

}

а) Объясните, почему f не является реентерабельной.
б) Предложите потокобезопасный вариант (без глобальных переменных).
в) Предложите эквивалент на Python без статического локала (используйте объект или замыкание). 

Упражнение 5. Анализ LEGB и ошибки UnboundLocalError (Python)
Дан код:

y = 10

def p():

    print(y)  # A

def q():

    print(y)  # B

    y = 5     # C

def r():

    y = 2

    def s():

        print(y)

    s()

p()

а) Укажите, что выведет p() и почему.
б) Объясните, почему q() вызывает UnboundLocalError и на какой строке.
в) Исправьте q() двумя способами: с global y и без глобальной модификации (переименуйте локальную).

Заключение

Локальные переменные – базовый инструмент дисциплины программирования: они изолируют состояние, упрощают доказуемость корректности и уменьшают риски ошибок. Освоение правил области видимости, времени жизни и места хранения, умение работать с замыканиями и аккуратно оценивать стек при рекурсии напрямую повышают качество решений на ЕГЭ и формируют профессиональные навыки разработки.