Вернуться наверх
aco.ifmo.ru photonic
вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


1.10. Размещение программ и данных в памяти

Все компиляторы языка программирования генерируют код, который во время выполнения хранится в оперативной памяти. Размещение данных в памяти, чтобы память была зарезервирована в exe-модуле, осуществляется по формуле:

Определение Объявление = инициализация;

int i=1; // тип идентификатор=значение

Время жизни переменных – это время, в течение которого переменная хранится в определенной области памяти. Время жизни переменных полностью определяется программистом. С понятием время жизни тесно связано понятие видимости (действия) переменных, которое бывает:

  • глобальное, когда в любой момент во время работы с переменной всегда ассоциирована область памяти и обратиться к ней можно из любой точки программы;
  • статическое, когда во время работы с переменной ассоциирована область памяти, но обратиться к ней можно только из определенных точек программы;
  • локальное, когда при каждом входе в блок операторов { } для хранения переменной выделяется область памяти, а при выходе память освобождается и переменная теряет свое значение.

Для управления статическим размещением переменных в памяти, их временем жизни и областью видимости язык программирования C++ предоставляет понятие классов памяти и ряд ключевых слов модификаторов типа:

  1. extern используется для определения глобальных переменных. Память для переменных extern распределяется постоянно. Такая переменная глобальна для всех функций и доступна в любой точке программы. Значение переменной всегда сохраняется.
  2. static используется для определения статических переменных. Статические определения используются в случае если необходимо сохранять предыдущее значение при повторном входе в блок операторов { }. Такая переменная инициализируется единственный раз, когда программа встречает ее объявление.
  3. auto используются для определения автоматических переменных. Переменные определенные внутри функции или блока операторов { } по умолчанию являются автоматическими. При входе в блок { } программа автоматически располагает переменную в сегменте стека. При выходе из блока память освобождается, а значения теряются.
  4. register используются для определения регистровых переменных. Переменные с классом памяти register, ассоциируются со скоростными регистрами памяти процессора. Но это не всегда возможно, поэтому часто компилятор преобразует такие переменные к классу auto.

Переменные extern и static явно не инициализированные программистом устанавливаются системой в нуль. Переменные auto и register не инициализируются и могут содержать "мусор".

Глобальные переменные создаются путем размещения их объявлений за пределами определений любых классов или функций. Глобальные переменные сохраняют свои значения в течение всего выполнения программы. На глобальные переменные и функции может ссылаться любая функция, которая расположена в исходном файле после их объявления или описания.

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

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

Программа демонстрирует области действия глобальных переменных, автоматических локальных переменных и статических локальных переменных.

/////////////////////////////////////////////////////////////////////////////
// Прикладное программирование
// Пример 13. Область действия переменных
// 
// Кафедра Прикладной и компьютерной оптики, http://aco.ifmo.ru
// Университет ИТМО
/////////////////////////////////////////////////////////////////////////////
// подключение библиотеки ввода-вывода
#include <iostream>
// подключение стандартного пространства имен для использования библиотек
using namespace std;

// прототипы функций 
void use_local();      
void use_static_local(); 
void use_global();      
/////////////////////////////////////////////////////////////////////////////
int x = 1; // глобальная переменная 
/////////////////////////////////////////////////////////////////////////////
void main() 
{ 
    int x = 5; // переменная, локальная в main 

    cout<<"local x="<<x<<endl; 

    { // скобки начинает новую область действия 
        int x = 7; // скрывает х во внешней области действия 
        cout<<"local x inside { ="<<x<<endl; 
    } // конец новой области действия 
    cout<<"local x after { ="<<x<<endl; 
    x++;
    cout<<"local x++ after { ="<<x<<endl; 

    use_local();        // use_local имеет локальную х 
    use_static_local(); // use_static_local имеет статическую локальную х 
    use_global();       // use_global использует глобальную х 

    use_local ();       // use_local повторно инициализирует свою локальную х 
    use_static_local(); // статическая локальная х сохраняет значение 
    use_global();       // глобальная х также сохраняет свое значение 

    cout<<endl<<"local x="<<x<<endl; 
}
/////////////////////////////////////////////////////////////////////////////
// функция реинициализирует локальную х при каждом вызове 
void use_local() 
{ 
    int x = 25; // инициализируется при каждом вызове функции 

    cout<<endl<<"use_local: x="<<x<<endl; 
    x++; 
    cout<<"use_local: x++="<<x<<endl; 
} 
/////////////////////////////////////////////////////////////////////////////
// функция инициализирует статическую локальную переменную х 
// только при первом вызове функции; между вызовами этой функции 
// значение х сохраняется 
void use_static_local() 
{ 
    static int x = 50; // инициализируется при первом вызове функции 

    cout<<"use_static_local: x="<<x<<endl; 
    x++; 
    cout<<"use_static_local: x++="<<x<<endl; 
} 
/////////////////////////////////////////////////////////////////////////////
// функция модифицирует глобальную переменную х при каждом вызове 
void use_global() 
{ 
    cout<<"use_global: x="<<x<<endl; 
    x *= 10; 
    cout<<"use_global: x*10="<<x<<endl; 
} 
/////////////////////////////////////////////////////////////////////////////

Константные переменные

Ключевое слово сonst означает что переменная инициализируется один раз после объявления и ее значение не модифицируемое:

const double pi=3.14159265358979; 

Еще один вариант использования глобальных констант:

#define PI 3.14159265358979