Объявление и инициализация переменных — краеугольный камень языка C с очень строгими и иногда неочевидными правилами. От того, как и где вы объявили переменную, будет зависеть даже её начальное значение (про инициализацию), а также связь с объектом памяти (про объявление и определение).
C восходит к временам, когда оптимизация памяти была приоритетом. Объявлять и инициализировать переменные разработчики должны были самостоятельно, иначе поведение программы становилось непредсказуемым. В современных C-компиляторах даже небольшое отклонение приводит к ошибкам линковки или неявной инициализации "мусором".
Основные ошибки:
Пример кода:
#include <stdio.h> int global_var; // определение, автоинициализация = 0 static int static_global_var; // static-файл, автоинициализация = 0 extern int extern_var; // объявление, определение где-то в другом месте void foo() { int local_var; // автоматическая, не инициализирована -> мусор static int static_local_var; // static, автоинициализирована в 0 }
Ключевые особенности:
1. Автоматические переменные (локальные без static и extern) инициализируются ли компилятором автоматически в 0?
Нет, содержат мусор. Их значение не определено, использовать до инициализации — ошибка.
2. Можно ли много раз определять переменную с extern в разных файлах?
Нет, нужно одно определение, остальные — объявления через extern, иначе linker выдаст ошибку "multiple definition" или "undefined symbol".
3. Чем отличается объявление функции от её определения?
Объявление — только прототип (без тела); определение — обязательно содержит тело функции. Для переменных объявление через extern не резервирует памяти, а для функции обе формы разрешены.
Объявляется глобальная переменная int counter; в двух заголовочных файлах. Проект слинковался с ошибкой multiple definition.
Плюсы:
Минусы:
В header прописан extern int counter;, определение int counter = 0; — только в одном C-файле.
Плюсы:
Минусы: