Similar presentations:
Указатели. Лекция 5. Виды оперативной памяти
1. Указатели
Лекция 52. Виды оперативной памяти
Современные языки программированияработают с тремя видами памяти:
• статической,
• автоматической,
• динамической
3. Статическая память
В статической памяти располагаются:• переменные, определения которых расположены
вне каких-либо функций или блоков (глобальные
переменные);
• переменные, определенные внутри функций или
блоков с использованием спецификатора static
(локальные статические переменные);
• коды функций
4. Статическая память
Программные объекты (переменные ифункции), размещенные в статической памяти,
существуют с момента начала выполнения
программы и до ее завершения
5. Автоматическая память
В автоматической памяти располагаются:• переменные, определения которых расположены
внутри каких-либо функций или блоков (локальные
переменные);
• фактические параметры функций, передаваемые им
при вызове
Переменные, размещенные в автоматической
памяти, существуют до момента завершения
выполнения функции после чего
автоматическая память очищается
6. Динамическая память
Каждой выполняющейся программевыделяется область памяти, которую
называют динамической памятью
Динамическая память используется для
размещения переменных и структур данных,
создаваемых в процессе выполнения программ
Такие переменные называются динамическими
переменными
7. Динамические переменные
создаются впроцессе выполнения программы
выполнением унарной операции new и
существуют до их удаления унарной операцией
delete
Особенности динамических переменных:
• эти переменные не имеют имен;
• это неинициализированные переменные, поэтому
перед использованием они должны быть
инициализированы
8. Адреса оперативной памяти
Оперативная память представляет собойпронумерованную последовательность байт
Номер байта памяти называется его адресом
Адрес – это целое число, которое принято
представлять в шестнадцатеричной системе
счисления
Диапазон адресов занимает интервал от 0 до
некоторого максимального значения,
определяемого архитектурой компьютера и
операционной системой
9. Ячейки памяти
В дальнейшем будем полагать максимальноезначение адреса равным 232 -1
Для каждого типа данных стандартом языка С+
+ определяется минимально возможное
количество байт, отводимое для хранения
значений этого типа
Такая область памяти называется ячейкой
памяти
Адрес ячейки памяти совпадает с адресом ее
первого (младшего) байта
10. Адреса динамических переменных
Доступ к динамическим переменным возможентолько путем непосредственного указания их
адреса в оперативной памяти
Адрес динамической переменной является
результатом выполнения операции new
Для хранения адресов используются
переменные, называемые указателями
11. Указатели
Таким образом,указатели – это
переменные,
хранящие адреса
других
программных
объектов
указатель q
002EFE8
0
002EFE8
0
указатель p
5
переменная X с
адресом 002EFE80
12. Объявление указателей на переменные и константы
Синтаксис объявления указателя напеременную:
<тип переменной> *<имя указателя>;
Указатели на константы объявляются со
спецификатором const
Например:
float *x, *b; const int *c;
Здесь объявлены два указателя x и b на
переменные вещественного типа а также
указатель c на целую константу
13. Указатели-константы
Кроме того, константами могут быть самиуказатели, т.е. содержать адреса, не
меняющиеся в течение всего времени их
существования
Это свойство указателей устанавливается
квалификатором const, записанным после
символа ‘*’ в объявлении указателя, например:
double *const cp; // указатель-константа на
переменную
const double *const cp; // указательконстанта на константу
14. Обращение к указанным переменным и константам
Переменная (константа), адрес которойхранится в некотором указателе, называется
указанной переменной (константой)
Синтаксис обращения к указанным
переменным и константам:
*<имя указателя>
Здесь символ “*” означает унарную операцию
разадресации, результатом которой является
получение значения из ячейки памяти, адрес
которой хранится в указателе
15. Инициализация указателей на переменные и константы
1.Присваивание указателю адреса
существующей переменной (константы):
int a; int *p = &a;
2.
Присваивание значения другого
инициализированного указателя:
int *r = p;
3.
Присваивание пустого значения:
int *p = NULL; int *r = 0;
4.
Присваивание адреса памяти в явном виде
int *p = (int*) 28456;
16. Замечания об инициализации
В первом способе инициализации используетсяунарная операция получения адреса
Эта операция может применяться только к
поименованным величинам; нельзя получить
адрес выражения или неименованной
константы
Четвертый способ инициализации
используется в системном программировании
для доступа к ячейкам памяти специального
назначения
17. Важность инициализации
При объявлении указателя надо сразувыполнять его инициализацию
Непреднамеренное использование
неинициализированных указателей – один из
наиболее распространенных источников
ошибок в программах!
18. Динамические переменные
(константы)создаются в динамической области памяти
(heap – куча)
Время жизни таких переменных – от момента
создания до завершения программы или до
явного освобождения памяти
Доступ к динамическим переменным и
константам осуществляется с помощью
указателей
19. Создание динамических переменных
происходит в момент выделения им места впамяти
Для выполнения этой операции можно
используют унарную операцию new
Синтаксис операции:
new <тип> [(<инициализирующее выражение>)]
Например:
int* m = new int;
float* x = new float(56);
20. Удаление динамических переменных
Для удаления динамических переменных иконстант с освобождением памяти используют
унарную операцию delete:
delete <имя указателя>
Память, отведенная под динамические
объекты, автоматически освобождается, когда
указатели на них выходят из области своего
действия
21. Сборка мусора
Вместо использования операций delete можнопросто присваивать переменной-указателю
значение NULL
В этом случае в оперативной памяти остается
неиспользуемая динамических переменная
В состав операционной системы входит
подсистема garbage collector («сборщик
мусора»), назначением которой является
автоматическое удаление из динамической
памяти неиспользуемых переменных
22. Пример программы
Программа «Объявление указателей»Листинг программы
23. Указатели void
Синтаксис объявленияvoid *<имя указателя>
Применяется в тех случаях, когда конкретный
тип объекта, адрес которого требуется
хранить, не определен
24. Указатели void
Указателю на void можно присвоить значениеуказателя любого типа, но перед выполнением
каких-либо действий с областью памяти, на
которую он ссылается, требуется произвести
явное преобразование к нужному типу
Например:
float a = 7; void *r = &a;
cout << “*r = “ << *(float*)r << endl;
25. Операции с указателями
Кроме четырех рассмотренных выше унарныхопераций (*, &, new и delete) для
указателей определены четыре бинарных
арифметических операции:
• инкремент,
• декремент,
• сложение с константой,
• вычитание
Арифметические операции изменяют значения
указателей
26. Операции с указателями
Операция инкремента (декремента)увеличивает (уменьшает) значение указателя,
связанного с некоторым типом, на величину,
равную размеру данных этого типа
Операции сложения (вычитания) с константой
увеличивают (уменьшают) значение указателя
на величину, равную произведению константы
на размер данных типа, связанного с
указателем
27. Операции с указателями
Разность двух указателей одного типа равнаразности их значений, деленной на размер
данных связанного с ними типа
Суммирование двух указателей не допускается
Например для указателей p и q:
int *p = new int, *q = new int;
разность p – q будет иметь значение в 4 раза
меньшее разности их значений
Листинг программы
28. Указатели и массивы
В языке C++ указатели играют очень важную роль,обеспечивая ряд особенностей в работе с массивами и строками,
которые отсутствуют в алголоподобных языках типа Pascal
29. Указатели и массивы
В языках C и C++ существует тесная связьмежду массивами и указателями – имя массива
фактически является указателем-константой,
инициализированным адресом начального
элемента массива
Поэтому возможна следующая инициализация
указателя:
float a[10]; float* p = a;
без выполнения операция получения адреса,
примененной к имени массива (&a)
30. Указатели и массивы
Для обращения к элементам массива можноиспользовать операции адресной арифметики
Например, присваивание
float x = *(a + i);
эквивалентно
float x = a[i];
Пример использования имени массива как
указателя
Выполнение программы
31. Динамические массивы
Использование указателей позволяетсоздавать массивы, размер которых
определяется уже в процессе выполнения
программы
Такие массивы принято называть
динамическими
Однако следует иметь в виду, что будучи
однажды заданным размер динамического
массива уже не может быть изменен
32. Создание динамического массива
Для создания динамического массиванеобходимо объявить указатель, который
будет играть роль имени массива:
<тип элементов> *<имя массива>
Затем делается запрос на выделение памяти
для размещения массива
<имя массива> = new <тип элементов>
“[“<выражение целого типа>”]”
Значение выражения, помещенного в
квадратные скобки, и будет размером
динамического массива
33. Освобождение памяти
Динамический массив не инициализируется иего элементы не обнуляются
Например:
cin >> n;
double *a = new double [n];
Освобождение памяти, выделенной под
динамический массив осуществляется
операцией
delete [ ] <имя массива>
Пример работы с динамическим массивом
Листинг программы
34. Двумерные массивы
с фиксированными наэтапе компиляции размерами объявляются
следующим образом:
<тип элементов> <имя массива>
“[“<размер1>”]” “[“<размер2>”]”
[=“{“<список констант>”}”],
где <размер1> и <размер2> – константные
выражения
35. Пример определения двумерного массива
Например:const int n = 2;
int a [n] [2 * n] = {{1, 3, 5, 7}, {2, 4,
6, 8}};
Здесь описан прямоугольный массив из двух
строк и четырех столбцов
Разбиение списка констант в инициализаторе
на подсписки можно было не производить:
int a [n] [2 * n] = {1, 3, 5, 7, 2, 4, 6,
8};
36. Двумерные массивы
В двумерном массиве a[i] являетсяуказателем-константой на начало i–й строки,
т.е. содержит адрес элемента a[i] [0], поэтому
*(a[i] + j) эквивалентно a[i] [j]
Следовательно, двумерный массив фактически
является одномерным массивом указателей на
одномерные массивы
Этот принцип построения распространяется на
массивы любой размерности
37. Двумерный массив
int a [5] [4]a
a [0]
a [0] [0]
a [0] [1]
a [0] [2]
a [0] [3]
a [1]
a [1] [0]
a [1] [1]
a [1] [2]
a [1] [3]
a [2]
a [2] [0]
a [2] [1]
a [2] [2]
a [2] [3]
a [3]
a [3] [0]
a [3] [1]
a [3] [2]
a [3] [3]
a 4]
a [4] [0]
a [4] [1]
a [4] [2]
a [4] [3]
38. Динамические двумерные массивы
Для создания динамического двумерногомассива следует объявить указатель на массив
указателей:
<тип элементов*> *<имя массива>
Далее следует запросить выделение памяти под
этот массив:
<имя массива> = new <тип элементов*>
“[“<выражение целого типа>”]”
39. Динамические двумерные массивы
Далее следует инициализировать каждый изэлементов массива указателей:
<имя массива> “[“<индексное
выражение>”]”= new <тип элементов>“[“<
выражение целого типа>”]”
40. Зубчатые массивы
Возможность задавать длину для каждойстроки двумерного массива позволяет
формировать массивы произвольной формы,
отличной от прямоугольной
Такие массивы называются зубчатыми (jagged
arrays)
Пример определения зубчатого массива
Листинг программы
Удаление многомерных динамических массивов
также производится операцией delete [ ]
41. Конец лекции
42. Структура физической памяти
Логическому делению оперативной памяти настатическую, автоматическую и динамическую
соответствует деление физической памяти на
несколько участков, называемых сегментами
Сегментная структура физической памяти
обеспечивает, кроме того, раздельное хранение
программ и данных
43. Сегменты оперативной памяти
44. Сегменты и виды памяти
Коды функций размещаются в сегменте командCS
Статические переменные размещаются в
сегменте данных DS
Автоматические переменные размещаются в
сегменте стека SS
Динамические переменные размещаются в
дополнительном сегменте данных ES
45. Виды указателей
Указатели могут использоваться для доступакак к статическим (поименованным), так и к
динамическим (непоименованным) объектам
Обращение к самим указателям
осуществляется по имени, также как к другим
статическим переменным
В языке C++ различают три вида указателей:
• указатели на переменные,
• указатели на функции,
• void-указатели
46. Указатели и строки
Пример работы со строками через указателиЛистинг программы