Глава 5. Использование динамической памяти
5.1 Адресация оперативной памяти.
Минимальная адресуемая единица памяти – байт.


0 1 2 3 4

Aсм

Аф

Физический адрес Аф – номер байта оперативной памяти.
Адресация по схеме «база+смещение»:
Аф = Аб + Асм,
где Аб – адрес базы – адрес, относительно которого считают
остальные адреса;
Асм – смещение – расстояние от базового адреса до физического.
Указатель – тип данных, используемый для хранения смещений.
В памяти занимает 4 байта, адресует сегмент размером V = 232 = 4 Гб.
Базовый адрес = адрес сегмента.

1

5.2 Указатели и операции над ними
[][][] [И2]*[=];
Где :
- признак изменчивости содержимого по адресу
указателя. Задается ключевым словом const. При этом
значение содержимого памяти, которую адресует
указатель, нельзя менять. Может отсутствовать.
- признак изменчивости указателя. Задается ключевым
словом const. При этом значение самого указателя
нельзя менять.
Может отсутствовать.
- тип данных, адресуемых указателем. Любой
тип, определенный в С++, в том числе void.
- тип указателя. Определяется моделью памяти.
Может быть far или near. Если тип указателя не указан,
принимается near.
2

Примеры определения указателей

ptrs
1) short

a, *ptrs =&a;

a

Указатель можно
инициализировать адресом
реальной переменной

2) const

short *ptrs;

3) short

*const ptrs=&a;

a

Неизменяемое значение:
можно ptrs = &b; нельзя
*ptrs=10;
Неизменяемый указатель
можно *ptrs=10; нельзя ptrs = &b;
3

5.2.1 Типизированные и нетипизированные
указатели
Различают указатели:
• типизированные – адресующие данные конкретного типа;
• нетипизированные – не связанные с данными
определенного типа.
Объявление типизированного указателя:

int *b,*c ;
float *s ,double *f;
long double *l;

Все указатели несут в
себе сведения о
размере памяти,
адресуемой этим
указателем

Объявление нетипизированного указателя:

void * ;
Этот указатель создан как бы «на все случаи жизни».
Он отличается от других отсутствием сведений о размере
соответствующего участка памяти. Поэтому его легко
связывать с указателями других типов.
4

Нулевой указатель
В С++ определена адресная константа NULL;
Эта константа определяет адрес, который никуда не
указывает или «нулевой указатель».
Его

можно присвоить указателю любого типа.

Например:

pi

0

float *pf=NULL;

pf

0

void *b=NULL;

b

0

int *pi=NULL;

Кроме того, эту константу можно использовать в
операциях сравнения при проверке логических
адресных выражениях.

while (pi!=NULL) do { …};
5

5.2.2 Операции над указателями
1. Присваивание.
Допускается присваивать указателю значение другого указателя того же типа
или нулевого указателя.
Пример:
int *p1,*p2;
float *p3,*p4;
void *p;...
{допустимые операции}
p1=p2;
p4=p3;
p1=NULL; p=NULL; ...
{недопустимые операции}
p3=p2;
p1=p3;
Однако, при необходимости выполнить операцию присваивания,
можно использовать явное переопределение типа, для
приведения указателя одного типа к другому.

p3=(float*)p2;
p2=(int*)p3;
p1=(int*)p;

Явное переопределение
типа указателя
6

Операции над указателями (2)
2. Получение адреса (&).
Результат операции – адрес некоторой области памяти, который
можно присвоить указателю.
Это можно сделать:
a) При помощи операции присваивания:
int *pi,i=10;
pi
... pi=&i;
i
10

b) Во время инициализации указателя при его
b
определении:
5.7
float b=5.7;
pf
float *pf=&b;

Операции над указателями (3)
3. Доступ к данным по указателю (операция разыменования). Полученное
значение имеет тип, совпадающий с базовым типом данных указателя.
Нетипизированные указатели разыменовывать нельзя.
Примеры:
b

short c, a=5,*ptri=&a; float d,p=2.4563;
void *b=&a;
1)

ptri

1 25
5
a

c=*ptri;

2) *ptri=125;

5

c

При необходимости разыменовать нетипизированный указатель требуется
выполнить явное преобразование типа.
b
b
3) *b=6; ? *(int*)b=6;
4) b=&p;
d=*b

a

5
6

p

?? d=*(float *)b
Явное переопределение типа указателя

8

Операции над указателями (4)
4. Операции отношения:
проверка равенства (==) и неравенства (!=).
Примеры:

int sign = (p1 == p2);
if (p1!=NULL) {….}
5.Арифметические операции.
В С++ над указателями разрешены операции:
- сложение и вычитание (аддитивные операции)
- инкремент или автоувеличение (++)
- декремент или автоуменьшение (--)
В силу особенностей выполнения арифметических операций
над указателями, совокупность этих операций получила
название Адресной арифметики

5.2.3 Адресная арифметика
+ n ? + n*sizeof()
Пример:
short a, *ptrs =&a;
1) ptrs++;

Значение
указателя
меняется

2)

Значение
указателя
меняется

ptrs+=4;

3) *(ptrs+2)=2;

Значение
указателя
не меняется!!!

Адресная арифметика (2)
Особенности результатов выполнения операций адресной
арифметики связано с реализацией языка С++.
В С++ принят обратный порядок размещения объектов в
памяти.
Это объясняется особенностями работы компилятора. При
разборе текста, компилятор распознает и размещает в
стек имена всех объектов, которые необходимо
разместить в памяти.
На этапе распределения памяти имена объектов выбираются
из стека и им отводятся смежные участки памяти. А так
как порядок записи в стек обратен порядку чтения,
размещение объектов оказывается обратным.
Например:

*&i2=

++*p=

int i1=10,i2=20,i3=30;

*&++i2=

*--p=

*p=

++*--p=

i1

i2

10

20

i3

30

*p++
*(p-1)=
направление увеличения адресов

Адресная арифметика (3)
// value
i2
// Ex5_1.cpp
cout
Соотношение ссылки и указателя

int a,
ptri
*ptri=&a, - указатель
&b=a;
- ссылка a=b

a=3; ? *ptri=3; ? b=3;
Основное отличие – для обращения к
содержимому по указателю нужна операция
разыменования,
обращение к содержимому по ссылке
осуществляется по имени ссылки!!!

4

5.3 Управление динамической памятью (С)
1. Размещение одного значения
Выделение памяти
void * malloc(size_t size); - возвращает адрес начала области
памяти; при присвоении указателю – явное преобразование типа.

Освобождение памяти
void free(void *block);
Пример:
int *a;
if ((a = (int *) malloc(sizeof(int))) == NULL)
{ printf("Не хватает памяти для числа.");
exit(1); }
*a=-244; *a+=10;
free(a);

Управление динамической памятью (С)
2. Размещение нескольких значений
Выделение памяти
void * сalloc(size_t n, size_t size);
Освобождение памяти
void free(void *block);
Пример:
int *list;
list = (int *) calloc(3,sizeof(int));
*list=-244;
list
*(list+1)=15;
*(list+2)=-45;

free(list);

4

4

4

Управление динамической памятью (С++)
1. Одно значение
Операция выделения памяти
=new[()];
Операция освобождения памяти
delete ;
Примеры:
а) int *k;
k = new int;
*k = 85;
б) int *a;
if ((a = new int(-244)) == NULL)
{printf("Не хватает памяти для числа.");
exit(1);
delete a;

}

Управление динамической памятью (С++)
2. Несколько значений
Операция выделения памяти для n значений:
=new[];

Операция освобождения памяти:
delete [ ] ;

Пример:

list

list+1

short *list;
2 2
list = new int [3];
*list=-244; *(list+1)=15; *(list+2)=-45;
delete[ ] list;

list+2

2

5.4 Многомерные массивы и указатели.
Объявление массива:
int *a;
|
int a[10];
a=calloc(10,4);
|
a[2]=15;

*(a+2)=15;

Примеры:
int list[10];
По правилам С++ имя массива является его адресом.
Поэтому для адресации элементов массива независимо от
способа описания можно использовать адресную
арифметику:

(list+i) ? &(list[i])
*(list+i) ? list[i]

Многомерные массивы и указатели (2)
int m[2][3][2];
m *m => m[0][][]
**m => m[0][0][]
***m => m[0][0][0]
m[0][2][]

m[0]

m[1]=>*(m+1)

m[0][2][0] => *(*(*(m+0)+2)+0) =>*(*(*m+2))
m[i][j][k] => *(*(*(m+i)+j)+k) =>*(*(*(i+m)+j)+k)

Многоуровневые ссылки (Ex5_1a)
int m[]={1,2,3,4};
int *mp[]={m+3,m+2,m+1,m};

mp
mp[0],*mp
mp[1],*(mp+1)
mp[2],*(mp+2)
mp[3],*(mp+3)

m
1
2
3
4

m[1],*(m+1)
или
mp[0][-2],
*(mp[0]-2),
*(*mp-2),
mp[1][-1],
*(mp[1]-1),
*(*(mp+1)-1)

Использование указателей при обработки массивов
Пример. Написать программу переформирования матрицы путем сортировки
каждой ее строки по возрастанию ее элементов.

Создание динамиеской матрицы
Указатель на
mas
// Ex5_2.cpp
указатель
#include "stdafx.h"
#include
#include
0
int **mas,*ptr;
1
int a,b,n,m,i,j,k;
2
void main()
3
{ printf("\n input n= ");
scanf("%d",&n);
Одномерные массивы
printf("\n input m= ");
целого типа
scanf("%d",&m);
Массив указателей
mas=new int * [n];
for(i=0;i
Использование указателей при обработки массивов (2)
Заполнение матрицы данными
for(i=0;i
Использование указателей при обработки массивов(3)
Сортировка строк матрицы

Использование вспомогательного
указателя для перестановок

for(i=0;i

Случайные презентации

Файл
обложка.ppt
234883.pptx
tlist.ppt
153200-6.ppt
обложка.ppt




Чтобы не видеть здесь видео-рекламу достаточно стать зарегистрированным пользователем.
Чтобы не видеть никакую рекламу на сайте, нужно стать VIP-пользователем.
Это можно сделать совершенно бесплатно. Читайте подробности тут.