Лекция 9: Области видимости переменных
Чак Норрис получил права, когда ему было 16 секунд.
Что такое память компьютера?
Память компьютера — это место, где хранятся данные и команды программ. Она состоит из ячеек, каждая из которых имеет уникальный адрес. Память работает по принципу записи и считывания данных с заданного адреса. Каждая ячейка памяти содержит определённое количество битов (обычно 1 байт = 8 бит), и данные в этих ячейках могут быть как инструкциями, так и значениями переменных программы.
Принципы работы памяти:
- Однородность — данные и команды программы хранятся в единой памяти.
- Адресность — доступ к данным осуществляется через адреса. Адрес переменной указывает на ячейку памяти, в которой она хранится.
- Иерархичность — память организована на разных уровнях, таких как кеш-память, оперативная память и дисковая память. Каждый уровень имеет свои характеристики по скорости и стоимости.
Пример:
int a = 10; // Переменная 'a' занимает 4 байта (на 32-битной архитектуре)
printf("Адрес переменной a: %p", &a); // Вывод адреса переменной
Области видимости переменных
Область видимости переменной — это часть программы, в которой переменная доступна для использования. В языке Си переменные могут быть локальными (внутри функций или блоков) или глобальными (доступными во всей программе).
Локальные переменные
Локальные переменные объявляются внутри функции или блока {}
и существуют только в пределах этой области. Они уничтожаются, как только управление выходит из этого блока.
Пример:
void func() {
int x = 5; // Локальная переменная
printf("x = %d", x); // Доступно только здесь
}
// printf("x = %d", x); // Ошибка: x недоступно вне func
Глобальные переменные
Глобальные переменные объявляются вне всех функций, обычно в начале программы, и доступны всем функциям, которые находятся в этом файле. Если они объявлены как extern
в других файлах, они могут быть использованы и там.
Пример:
int global = 10; // Глобальная переменная
void func() {
printf("global = %d", global); // Доступно в любой функции этого файла
}
Сравнение локальных и глобальных переменных
- Локальная переменная существует до конца блока, где она была объявлена.
- Глобальная переменная существует до конца выполнения программы, и доступна в любой функции, после её определения.
Классы памяти
Класс памяти определяет время жизни переменной (сколько времени она существует) и её область видимости. В языке Си существуют следующие классы памяти:
1. Автоматический класс (auto)
Переменные по умолчанию имеют класс auto. Они создаются при входе в блок кода и уничтожаются при выходе из него. Эти переменные хранятся в стеке.
Пример:
void func() {
auto int x = 5; // Локальная переменная, класс auto
printf("x = %d", x);
}
Переменная x
существует только в функции func
, и память под неё освобождается, как только выполнение функции завершится.
2. Статический класс (static)
Переменные с классом static сохраняют своё значение между вызовами функции, но доступны только в своей области видимости. Если такая переменная определена в функции, она сохраняет своё значение между вызовами функции, а если в глобальной области, она ограничена текущим файлом.
Пример:
void counter() {
static int count = 0; // Статическая переменная
count++;
printf("count = %d\n", count);
}
int main() {
counter(); // Вывод: count = 1
counter(); // Вывод: count = 2
return 0;
}
Переменная count
сохраняет своё значение между вызовами функции counter
.
3. Регистровый класс (register)
Переменные с классом register могут быть размещены в регистрах процессора, что ускоряет доступ к ним. Такие переменные не имеют явного адреса и не могут быть использованы с оператором &
(например, нельзя получить адрес).
Пример:
void func() {
register int i; // Переменная будет попытаться размещена в регистре
for (i = 0; i < 10; i++) {
printf("%d ", i);
}
}
4. Внешний класс (extern)
Переменные с классом extern определяются в одном файле и могут быть использованы в других файлах программы. Они позволяют работать с глобальными переменными, которые определены в другом месте программы.
Пример:
file1.c:
int global = 100; // Определение внешней переменной
file2.c:
extern int global; // Объявление внешней переменной
printf("global = %d", global);
Переменная global
доступна в любом файле программы после её объявления как extern
.
Объявление и определение переменной
Объявление переменной сообщает компилятору о её существовании, но не выделяет для неё памяти. Определение переменной выделяет память и может (но не обязательно) инициализировать её значением.
Пример:
extern int x; // Объявление переменной
int x = 10; // Определение переменной
- Объявление с помощью
extern
позволяет компилятору знать о существовании переменной. - Определение выделяет память для переменной и присваивает ей начальное значение.
Правила:
- Глобальные переменные объявляются с использованием
extern
, а определяются в одном файле. - Статические переменные сохраняют своё значение между вызовами, но остаются доступными только в пределах своей области видимости.
Класс памяти для функций
Функции в языке Си могут быть объявлены и определены с классами памяти static и extern.
- extern (по умолчанию): Функция видна в других файлах программы.
- static: Функция доступна только в текущем файле.
Пример:
file1.c:
static void hidden() {
printf("Эта функция доступна только в file1.c");
}
void visible() {
printf("Эта функция доступна в других файлах");
}
file2.c:
extern void visible(); // Функция доступна в других файлах
visible(); // Работает
hidden(); // Ошибка: нельзя вызвать, так как она статична
- Функция
visible
сextern
доступна в других файлах. - Функция
hidden
сstatic
доступна только в файлеfile1.c
.
Заключение
- Локальные переменные используются для хранения временных данных и существуют только в пределах блока или функции, в которых они объявлены.
- Глобальные переменные полезны для данных, которые должны быть доступны нескольким функциям в разных частях программы.
- Использование static помогает ограничить область видимости переменной или функции, а использование register ускоряет выполнение.
- Используйте extern, чтобы объявить переменные или функции, которые будут использоваться в разных файлах программы.