История вопроса:
Глобальные и локальные переменные появились в C для управления памятью и областью видимости кода. Глобальные переменные раньше были основным способом обмена данными между функциями ещё до появления модульного программирования, локальные же позволили уменьшить взаимодействие и повысить изоляцию кода.
Проблема:
Часто возникает недопонимание разницы между глобальными и локальными переменными: сроки их жизни, область видимости, правила и время инициализации. Глобальные переменные приводят к проблемам с синхронизацией и читаемостью, локальные — к недоступности нужных данных. Ошибки в понимании этих отличий приводят к багам и затрудняют масштабирование кода.
Решение:
Глобальные переменные объявляются вне всех функций и доступны во всех файлах при использовании extern. Их срок жизни — вся программа, и инициализация производится либо неявно нулями (для статических переменных), либо явно значением пользователя. Локальные переменные объявляются внутри функций, их срок жизни ограничен вызовом функции и их содержимое не инициализируется автоматически.
Пример кода:
int g_var = 42; // Глобальная переменная void foo() { int l_var = 5; // Локальная переменная }
Ключевые особенности:
Инициализируется ли локальная переменная автоматически нулём, если не задано начальное значение?
Нет. Только глобальные и статические переменные инициализируются нулями по умолчанию. Локальные переменные содержат «мусор» (неопределенное значение), если явно не задать стартовое значение.
Пример:
void test() { int a; printf("%d ", a); // Неопределенное поведение }
Из разных файлов всегда ли можно обратиться к глобальной переменной?
Нет. Если переменная объявлена как static вне функции, она видна только в этом исходном файле. Если нужна глобальная видимость, используйте extern.
Можно ли объявить глобальную переменную внутри функции?
Нет. Внутри функции все объявления — локальные. Только вне функций можно создавать глобальные переменные.
Глобальная переменная используется для обмена данными между функциями:
int error_code; void f1() { error_code = 1; } void f2() { if (error_code) ... }
Плюсы:
Минусы:
Все переменные локальные, данные передаются через параметры функций:
void f1(int *err) { *err = 1; } void f2(int err) { if (err) ... }
Плюсы:
Минусы: