Классы памяти

advertisement
1
Классы памяти
Переменная-это именованная область памяти.
Имя переменной –это ссылка на некоторую область памяти.
Переменная - частный случай леводопустимого выражения
Леводопустимое выражение – это конструкция для
обращения к некоторому участку памяти, куда можно поместить
значение (l – value, l-значение).
Понятие леводопустимого выражения включает все
возможные формы обращения к некоторому участку памяти с
целью изменения его содержимого.
Леводопустимые выражения:
1) имена скалярных переменных
2) имена элементов массивов
3) имена указателей
4) ссылки на l-value (синонимы l-value)
5) имена элементов структурированных данных
имя структуры . имя элемента
указатель на структуру -> имя элемента элемента
6) выражения с операцией ‘*’
int i , * p =&i;
*p=7; *&i=2;
7)вызовы функций возвращающих ссылки на объекты программы
Примеры праводопустимых выражений:
1) любое арифметическое, логическое и т. д. выражение
2) имя константы
3) имя функции (указатель константа)
4) имя массива (указатель константа)
5) вызов функции, не возвращающей ссылки
2
В дальнейшем рассмотрении, в качестве l-value будет
рассматриваться переменная.
Переменные характеризуются типами, а также классами
памяти.
Класс памяти
Класс памяти определяет:
1) место размещения переменной (ОП или регистры)
2) область действия имени (идентификатора), связанного с
переменной
3) видимость объекта
4) время существования
5) тип компоновки (связывания)
Явно задать класс памяти можно с помощью спецификаторов:
auto, register, static, extern.
Место размещения
Ниже указаны спецификаторы класса памяти и
соответствующее им место размещения объекта:
 auto - автоматическая, локальная оперативная память
(стек - временная память).Спецификатор auto может быть
задан при определении переменной блока, например в теле
функции. Этим объектам память выделяется при входе в
блок и освобождается при выходе из него. Вне блока
переменные класса auto не существуют.
 register - автоматическая регистровая память (регистры
процессора). Спецификатор register аналогичен auto, но для
размещения переменной используется не оперативная
память, а регистры процессора. Если регистры заняты
другими переменными, переменные класса register
обрабатываются как объекты класса auto.
3
 static
- статическая
(сегмент данных). Объект этого
класса будет существовать в пределах того файла
программы, где он определен. Этот класс может быть
приписан как переменным, так и функциям.
 extern - внешняя, глобальная память (сегмент данных).
Объект класса extern глобален, то есть, доступен во всех
файлах программы. Этот класс может быть приписан как
переменным, так и функциям.
Класс памяти переменной определяется
1) по умолчанию размещением определения переменной в
программе;
2) синтаксисом определения переменной
- наличием
спецификаторов, присутствующих в определении переменной.
Область действия (ОД) имени
ОД – это часть программы, в которой можно обращаться к
данному имени (сфера действия имени в программе).
Рассмотрим все случаи:
1) Имя определено в блоке (локальные переменные):
точки определения до конца блока;
ОД - от
2) Формальные параметры в определении функции (форм. пар. это локальные переменные функции) : ОД параметров – блок
тела функции;
3) Метки операторов: ОД – функция;
4) Глобальные объекты: ОД - вся программа от точки их
определения или от точки их описания;
4
5) Формальные параметры в прототипе функции: ОД- прототип.
Область видимости (ОВ)
Понятие области видимости понадобилось в связи с
возможностью повторных определений идентификатора внутри
вложенных блоков или функций. В этом случае разрывается связь
имени переменной с участком памяти, хотя сфера действия
имени сохраняется.
ОВ – это часть программы, в которой реально обращение к
имени переменной позволяет обратиться к данному участку
памяти.
ОВ может быть меньше ОД, если внутри блока, где
определена переменная, имеется внутренний блок, в котором то
же имя дано другой переменной (то есть, связано с другим
участком памяти). Тогда во внутреннем блоке внешняя
переменная теряет видимость.
ОД >= ОВ
int k
Пример1:
#include<iostream.h>
int k=0;
void main()
{ int k=1;
{ cout<< k;
char k = 'A';
cout<< k;
cout<< ::k;
cout << k ;
} cout << k ;
}
результат : 1A0A1
char k
5
Пример2:
int a;
// определена глобальная переменная а
void main()
{ extern int a, b; …}
//описаны две глобальных переменных,
//причем одна еще не определена, но использовать b после
//описания можно
void func1 ( )
{extern int b; …} // описана глобальная переменная b до
//определения и
ее можно использовать в теле функции,
//доступна также переменная a
void func2 ( )
{…}
// a – доступна , b – не доступна, т.к. не было еще ее
//определения
int b; // определение глобальной переменной b
void func3( )
{ int a; … } // глобальная a потеряла видимость, т.к. объявлена
//локальная переменная с тем же именем, глобальная b - видна
void func4 ( )
{int b; …} // видна глобальная переменная a
// , а глобальная b - потеряла свою видимость, т.к. объявлена
//локальная переменная b с тем же именем.
Продолжительность существования
Продолжительность существования - это время, в течение
которого, идентификаторы соответствуют участкам памяти.
Бывает
статическая,
локальная
и
динамическая
продолжительность.
При статической продолжительности память выделяется
при определении объекта и сохраняется до конца программы.
1) По - умолчанию все глобальные переменные (т.е. объявленные
вне всех функций) обладают статической продолжительностью.
2) Локальные переменные (объявленные в функциях), со
спецификатором
statiс
также
имеют
статическую
продолжительность.
6
3) Статическая переменная, локализованная в функции, не
теряет своего значения при отработке функции.
Инициализируется статическая переменная только при
первом вызове функции, при втором вызове и т. д. – начальное
значение этой переменной будет то, что сохранилось при
предыдущем вызове.
4)Глобальные и статические переменные по умолчанию
инициализируются нулями.
5) Статическую продолжительность имеют все функции.
6) Если в функции имеется описание переменной со
спецификатором extern,
это означает, что в функции
представлено описание некоторой внешней переменной,
определение которой дано в другом месте. Такая переменная
имеет статическую продолжительность существования.
Пример:
… int V ( void)
{ static int k;
//статическая переменная инициализирована 0
return ++k;
}
void main ()
{ int k=0;
// другая локальная переменная
for( ; k <=3 ; k++) cout<< “\n”<<V ( ) ;
}
1
2
3
4
Локальной продолжительностью существования обладают
автоматические (локальные) переменные, объявленные в блоке.
При входе в блок, переменной выделяется место на регистрах
процессора, или в оперативной памяти - в стеке и память
освобождается при завершении блока.
Должна быть явная инициализация локальных переменных,
иначе их начальное значение не предсказуемо.
7
Отметим еще раз, если локальная переменная, объявленная
в функции (т.е. локальная область действия), но со
спецификатором static, эта переменная имеет статическую
продолжительность существования - до конца программы.
Объекты с динамической продолжительность создаются и
уничтожаются с помощью операторов в процессе выполнения
программы по желанию программиста. Память таким
переменным выделяется в динамической области памяти,
называемой кучей. Продолжительность от точки объявления до
момента программного освобождения памяти или до конца
программы, если память программно не была освобождена.
Для выделения памяти используются операция new и
функция malloc(), прототип которой находится в файле alloc.h:
void* malloc( int size);
size - размер в байтах, выделяемой памяти.
Функция возвращает значение указателя без типа, поэтому
при выделении памяти надо производить приведения типа.
Освобождение памяти происходит с помощью операции
delete и функции free ().
…
void main( )
{ int*m = (int*) malloc (sizeof(int)); //использование функции
// для выделения памяти на одну переменную типа int
free(m);
//освобождение памяти
// аналогично используя операцию:
int*r = new int ; delete r; // использование операций
}
Тип компоновки
Если программа состоит из нескольких файлов, каждому
имени, используемому в нескольких файлах, может
соответствовать следующие ситуации:
1) один объект, общий для всех файлов, таким объектам
компоновщик обеспечивает внешнее связывание;
8
2) один и более объектов в каждом файле, т.е. объекты,
локализованы в файлах, для них используется внутреннее
связывание;
Тип компоновки компилятор устанавливает по контексту.
Определения и описания
Все описанные выше атрибуты (тип, класс, ОД и т. д.)
приписываются объекту при его определении (объявлении) или
при его описании.
В чем разница между определением или описанием.
При определении (definition) или объявлении объекта ему
дается имя, и устанавливаются атрибуты объекта, в соответствии
с которыми выделяется нужный объем памяти и определяется
формат внутреннего представления объекта.
При определении происходит связывание имени объекта с
участком памяти.
Определение выполняет инициализацию объекта.
Определение объекта может быть только одно в программе!
Описание или декларация (declaration) дает знать
компилятору, что объект определен и напоминает свойства
объекта (в основном компилятор отслеживает типы!).
Таким образом, описание - это представление в конкретной
функции уже объявленного где – то объекта.
Описаний объекта может быть несколько!
Нередко описание и определение по внешнему виду
совпадают.
Не совпадают они в следующих случаях:
1)описание – прототип функции
2)описание содержит спецификатор extern
3)описывается класс или структурный тип
4)описывается статический компонент класса
5)описывается имя типа с помощью typedef
9
Определения
char c;
Описания
extern int g; -//переменная
//внешняя
const float pi=3.14;
extern const float pi- //внешняя
// конст.
float Func (float x) { return x*x} float Func (float x) ; //// прототип
struct {char a; int b;}st // // структура
float d = 1.0- инициализация
struct st ; //– имя структуры
// структуры без полей
typedef char symbol;
Определения(объявление) переменных
S m тип
имя1 иниц.1, имя2 иниц.2, … ;
S , m , иниц. -не обязательны
S -спецификаторы классов памяти auto , static , extern , register
m –модификатор:
const - указывает на постоянство объекта
valatile – указывает на изменчивость
непосредственного обращения к нему.
объекта
без
Инициализация проводится двумя способами:
имя = инициализирующее выражение;
имя (инициализирующее выражение) – применяется только в
функциях
Имя переменных:
1) Две глобальных переменных не могут иметь одинаковые
имена.
2) Локальная переменная может иметь одинаковое имя с
глобальной переменной и тогда в данном блоке становится
недоступна глобальная переменная с этим именем.
10
3) Локальные переменные разных блоков могут иметь
одинаковые имена, т.к. у них различные ОВ.
4) Локальные переменные одного блока должны иметь
различные имена, и если этот блок – тело некоторой
функции, то и имена формальных параметров должны быть
различными и не совпадать с именами локальных
переменных функции.
Download