В чем разница локальных и глобальных переменных в C
Что проверяют
Для тестировщика это вопрос про умение читать код и понимать, откуда берётся нестабильное поведение. Интервьюеру важно, различаете ли вы область видимости и время жизни. Следом обычно спрашивают про static внутри функции и про то, почему глобальное состояние мешает изоляции тестов.
Как отвечать
Разведите два понятия и добавьте детали:
- область видимости: локальная переменная видна только внутри блока
{}, где объявлена. Глобальная видна во всём файле ниже объявления, а из других файлов через объявлениеextern; - время жизни: локальная автоматическая переменная живёт, пока выполняется блок, обычно на стеке или в регистре. Глобальная существует всё время работы программы в статической памяти (секции
.dataи.bss); - инициализация: глобальные и
staticпеременные без явного значения обнуляются. Локальная автоматическая содержит мусор, и чтение её до присваивания это неопределённое поведение; staticу локальной: видимость остаётся локальной, а время жизни становится как у глобальной, значение сохраняется между вызовами;staticу глобальной: переменная не видна из других единиц трансляции, это внутреннее связывание.
Одноимённая с глобальной локальная переменная не ошибка компиляции, а сокрытие (shadowing): внутри блока работает она. Флаг -Wshadow в GCC и Clang предупреждает о таком.
Дальше свяжите с тестированием. Глобальное состояние переживает тест: если один кейс поменял счётчик, следующий стартует с грязными данными, и результат зависит от порядка запуска. В юнит-фреймворках для C вроде Unity или CMocka такие переменные сбрасывают в setUp.
Где спотыкаются
Говорят, что одинаковые имена у локальной и глобальной вызывают конфликт. Компилятор это пропустит, и именно поэтому такой код опасен: правка «глобальной» тихо меняет локальную.
Забывают, что локальная переменная не обнуляется. Тест может проходить в отладочной сборке и падать в релизной, потому что в стеке оказался другой мусор.
Считают безопасным вернуть из функции указатель на локальную переменную. После выхода из функции эта память ей уже не принадлежит, и поведение не определено, даже если код иногда «работает».