Russian Belarusian English German Japanese Ukrainian

4.115

Каждая переменная характеризуется некоторым классом памяти, который определяет ее время жизни, в течение которого эта переменная существует в памяти. Одни переменные существуют недолго, другие неоднократно создаются и уничтожаются, третьи существуют на протяжении всего времени выполнения программы. В C++Builder имеется четыре спецификации класса памяти: auto, register, extern и static. Спецификация класса памяти идентификатора определяет erq класс памяти, область действия и пространство имен. Областью действия (областью видимости) идентификатора называется область программы, в которой на данную переменную (как, впрочем, и на любой идентификатор - константу, функцию и т.п.) можно сослаться. На некоторые переменные можно сослаться в любом месте программы, тогда как на другие только в определенных ее частях.

Класс памяти определяется, в частности, местом объявления переменной. Локальные переменные объявляются внутри некоторого блока или функции. Эти переменные видны только в пределах того блока, в котором они объявлены. Блоком называется фрагмент кода, ограниченный фигурными скобками "{ }". Глобальные переменные объявляются вне какого-либо блока или функции.

Спецификации класса памяти могут быть разбиты на два класса: автоматический класс памяти с локальным временем жизни и статический класс памяти с глобальным временем жизни. Ключевые слова auto и register используются для объявления переменных с локальным временем жизни. Эти спецификации применимы только к локальным переменным. Локальные переменные создаются при входе в блок, в котором они объявлены, существуют лишь во время активности блока и исчезают при выходе из блока.

Спецификация auto, как и другие спецификации, может указываться перед типом в объявлении переменных. Например:

auto float х, у;

Локальные переменные являются переменными с локальным временем жизни по умолчанию, так что ключевое слово auto используется редко. Далее мы будем ссылаться на переменные автоматического класса памяти просто как на автоматические переменные. Пусть, например, имеется следующий фрагмент кода:

{
int i= 1;
...
i++;
...
}

к которому в ходе работы программы происходит неоднократное обращение. При каждом таком обращении переменная i будет создаваться заново (под нее будет выделяться память) и будет инициализироваться единицей. Затем в ходе работы программы ее значение будет увеличиваться на 1 операцией инкремента. В конце выполнения этого блока переменная исчезнет и выделенная под нее память освободится. Следовательно, в такой локальной переменной невозможно хранить какую-то информацию между двумя обращениями к блоку.

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

register int i = 1;

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

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

Ключевые слова extern и static используются, чтобы объявить идентификаторы переменных как идентификаторы статического класса памяти с глобальным временем жизни. Такие переменные существуют с момента начала выполнения программы. Для таких переменных память выделяется и инициализируется сразу после начала выполнения программы.

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

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

Локальные переменные, объявленные с ключевым словом static, известны только в том блоке, в котором они определены. Но в отличие от автоматических переменных, локальные переменные static сохраняют свои значения в течение всего времени выполнения программы. При каждом следующем обращении к этому блоку локальные переменные содержат те значения, которые они имели при предыдущем обращении.

Вернемся к уже рассмотренному выше примеру, но укажем для переменной i статический класс:

{
static int i = 1;
...
i++;
...
}

Инициализация переменной i произойдет только один раз за время выполнения программы. При первом обращении к этому блоку значение переменной i будет равно 1. К концу выполнения блока ее значение станет равно 2. При следующем обращении к блоку это значение сохранится и при окончании повторного выполнения блока i будет равно 3. Таким образом, статическая переменная способна хранить информацию между обращениями к блаку и, следовательно, может использоваться, например, как счетчик числа обращений.

Все числовые переменные статического класса памяти принимают нулевые начальные значения, если программист явно не указал другие начальные значения. Статические переменные - указатели, тоже имеют нулевые начальные значения.

Спецификации класса памяти extern используются в программах с несколькими файлами. Пусть, например, в модуле Unit1 в файле Unit1.cpp или Unit1.h (это безразлично) объявлена глобальная переменная:

int а = 5;

Тогда, если в другом модуле Unit2 в файле Unit2.cpp или Unit2.h объявлена глобальная переменная:

extern int а;

то компилятор понимает, что речь идет об одной и той же переменной. И оба модуля могут с ней работать. Для этого даже нет необходимости связывать эти модули директивой #include, включающей в модуль Unit1 заголовочный файл второго модуля.

Если заметили ошибку, выделите фрагмент текста и нажмите Ctrl+Enter

Добавить комментарий


Поиск по сайту