Указатели в С++
Указатели в С++
Указатели в С++
Указатели в С++
Размер указателей
Нулевой указатель
Указатели в С++
Арифметика указателей
Арифметика указателей
Указатели в С++
Указатели в С++
Указатели в С++
Указатели в С++
Указатели С++
Указатели в С++
Указатели в С++
Указатели в С++
Указатели в С++
Указатели в С++
Указатели в С++
Указатели в С++
Динамические массивы
Динамические массивы
Указатели в С++
Указатели в С++
1.22M
Category: programmingprogramming

Указатели в С++ (лекция 6)

1. Указатели в С++

Каждая переменная программы имеет свой адрес, для
хранения которого можно использовать указатель на
эту переменную.
Указатель - это переменная, значением которой
является адрес другой переменной. Так как указатель
может ссылаться на переменные разных типов, с
указателем в языке С++ связывается тип того объекта,
на который он ссылается.
Для описания указателей используется операция
косвенной адресации *.

2. Указатели в С++

Допустим, что переменная var1 имеет тип int. Чтобы
объявить указатель для хранения адреса этой
переменной нужно объявить переменную, например,
pVar, которая будет содержать адрес значения типа int.
Это описывается так :
int *pVar.
Унарная операция &, примененная к некоторой
переменной, показывает, что нам нужен адрес этой
переменной, а не ее текущее значение. Если указателю
нужно
присвоить
пустое
значение,
то
ему
присваивается значение 0.

3. Указатели в С++

Пример 1.
int var1=-15;
int *pVar=0;
pVar=&var1;
pVar1
100
50
var1
-15
100
101
102
103
104
105

4. Указатели в С++

Оператор
разыменования
(*)
перед
именем
переменной
pVar
может
рассматриваться
как
«значение, хранящееся по адресу».
*pVar=12;
cout<<var1; // var1=12
pVar1
100
50
var1
12
100
101
102
103
104
105

5. Размер указателей

Размер указателей зависит от архитектуры,
для которой скомпилирован исполняемый
файл – 32- битный исполняемый файл
использует 32-бтные адреса памяти.
Следовательно, указатель на 32-битной
машине занимает 32 бита (4 байта).
С 64-битным исполняемым файлом
указатель будет 64-битным (8 байтов).
При том размер указателя НЕ зависит от
размера объекта, на который он ссылается.
#include <iostream>
using namespace std;
int main()
{
char a = 'c';
int b = 5;
char * ch_ptr = &a;
int * i_ptr = &b;
cout<< sizeof(a)<<endl;
cout<< sizeof(b)<<endl;
cout<< sizeof(ch_ptr)<<endl;
cout<< sizeof(i_ptr)<<endl;
return 0;
}

6. Нулевой указатель

#include <iostream>
#include <locale.h>
using namespace std;
int main()
{
setlocale(0, "");
int *ptr = NULL;
cout<< ptr;
return 0;
}

7. Указатели в С++

Если переменная pVar объявлена как указатель, то
оператор присваивания pVar=&var1 означает: "взять
адрес переменной var1 и присвоить его значение
переменной-указателю pVar ".
Заметим, что если pVar — некоторый указатель, то
pVar ++ увеличивает его значение и он теперь
указывает на следующий, соседний адресуемый
объект. Значение pVar используется в выражении, а
затем увеличивается. Аналогично определяются
операции pVar --, ++ pVar, -- pVar. В общем случае
указатель pVar можно скаладывать с целым числом i.
Оператор pVar +=i передвигает ссылку на i элементов
относительно текущего значения. Эти конструкции
подчиняются правилам адресной арифметики.

8. Арифметика указателей

#include <iostream>
using namespace std;
nt main()
{
int n = 15;
int *n_ptr = &n;
cout <<"adress="<<n_ptr<<"\tvalue = "<<*n_ptr<<endl;
n_ptr++;
cout <<"adress="<<n_ptr<<"\tvalue = "<<*n_ptr<<endl;
n_ptr--;
cout <<"adress="<<n_ptr<<"\tvalue = "<<*n_ptr<<endl;
return 0;
}

9. Арифметика указателей

#include <iostream>
using namespace std;
nt main()
{
double n = 15.5;
double* n_ptr = &n;
cout <<"adress="<<n_ptr<<"\tvalue = "<<*n_ptr<<endl;
n_ptr++;
cout <<"adress="<<n_ptr<<"\tvalue = "<<*n_ptr<<endl;
n_ptr--;
cout <<"adress="<<n_ptr<<"\tvalue = "<<*n_ptr<<endl;
return 0;
}

10. Указатели в С++

Вернемся к массивам. Пусть имеется описание
short a[5];
Оно определяет массив размером 5 элементов, т.е.
пять последовательно расположенных ячеек памяти
a[0], a[1], a[2], a[3], a[4].
short a[5];
a
100
100
a[0]
a[1]
a[2]
a[3]
a[4]
4
8
-3
1
12
101
102
103
104
105
106
107
108
109

11. Указатели в С++

a
100
100
a[0]
a[1]
a[2]
a[3]
a[4]
4
8
-3
1
12
101
102
103
104
105
106
107
108
109
Адрес i-го элемента массива равен сумме адреса
начального элемента массива и смещения этого
элемента на i единиц от начала массива. Это
достигается индексированием: a[i] — i -й элемент
массива. Но доступ к любому элементу массива может
быть выполнен и с помощью указателей, причем, более
эффективно.

12. Указатели в С++

pVar
a
100
100
100
a[0]
a[1]
a[2]
a[3]
a[4]
4
8
-3
1
12
101
102
103
104
105
106
107
108
109
Если pVar — указатель на short, описанный как
short * pVar, то pVar после выполнения операции pVar
=&a[0] содержит адрес a[0], а pVar +i указывает на i -й
элемент массива. Таким образом, pVar +i является
адресом элемента a[i], а *( pVar +i) — содержимым i- го
элемента

13. Указатели в С++

pVar
a
100
100
100
a[0]
a[1]
a[2]
a[3]
a[4]
4
8
-3
1
12
101
102
103
104
105
106
107
108
109
(операции * и & более приоритетны, чем
арифметические операции). Так как имя массива в
программе отождествляется с адресом его первого
элемента, то выражение pVar =&a[0] эквивалентно
такому: pVar =a. Поэтому значение a[i] можно записать
как *(a+i). Применив к этим двум элементам операцию
взятия адреса, получим, что &a[i] и a+i идентичны.

14. Указатели С++

int main()
{
setlocale(0, "");
int mas[10];
int i;
for(i = 0; i < 10; i++)
cin>>mas[i];
cout<< "\nВыводим элементы массива:"<<endl;
for(i = 0; i < 10; i++)
cout<<*(mas+i)<<" ";
return 0;
}

15.

int main()
{
int mas[4]= {0, 2, 4, 6};
int *i, y;
cout<< &mas<< endl;
for(int j = 0; j < 4; j++)
cout<< &mas[j]<<" ";
i = &mas[0];
cout<< "\ni= "<< i<<endl;
Унарные операции '*', '--' , '++' имеют
одинаковый приоритет и при размещении
рядом выполняются справа налево.
y = *i;
cout<< "i= "<< i<<" y= "<< y<<endl;
y = *i++;
cout<< "i= "<< i<<" y= "<< y<<endl;
y = ++*i;
cout<< "i= "<< i<<" y= "<< y<<endl;
return 0;
}

16. Указатели в С++

Указатели применяются для:
• Размещения данных в свободных областях памяти и
доступа к ним;
• Доступа к переменным и функциям классов;
• Передачи параметров в функции по ссылке.

17. Указатели в С++

Память условно разделена на пять областей:
• Область глобальных переменных
• Свободная, или динамически распределенная
память;
• Регистровая память (регистры);
• Сегменты программы;
• Стековая память.

18. Указатели в С++

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

19. Указатели в С++

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

20. Указатели в С++

В отличие от стека переменных, ячейкам свободной
памяти
нельзя
присвоить
имя.
Доступ
к
ним
осуществляется посредством указателя, хранящего
адрес нужной ячейки.
В отличие от стековой памяти, динамическая память не
очищается до завершения работы программы, поэтому
освобождением памяти должен заниматься
программист.

21. Указатели в С++

Оператор new
Для выделения памяти в области динамического
распределения используется ключевое слово new.
Пример
int *pVar = new int;
float * pVar2 = new float;
В каждом случае указатели pVar и pVar1 будут
указывать на ячейку памяти в области динамической
памяти,
содержащую
значение
int
и
float
соответственно.

22. Указатели в С++

Оператор delete
Если память, выделенная под переменную больше не
нужна, ее следует освободить с помощью оператора
delete.
Пример
int *pVar = new int;
delete pVar;
При этом происходит не удаление указателя, а
освобождение области памяти по адресу, записанному
в нем.

23. Динамические массивы

Чтобы создать динамический массив будем использовать конструкцию ниже:
<тип _данных> *<имя_массива> = new <тип_переменных> [<количество_ячеек>]
Для удаления динамического массива используем оператор delete:
delete [] <имя_массива>

24. Динамические массивы

int main()
{
setlocale(0, "");
int n;
cout<<"Введите количество чисел:";
cin>>n;
cout<< "Введите "<< n << " чисел"<<endl;
int *d_array = new int[n];
for(int i = 0; i<n; i++)
cin>>d_array[i];
cout<<"Выводим элементы массива:"<<endl;
for(int i = 0; i<n; i++)
cout<<d_array[i]<<" ";
cout<< "\nУдаляем массив!";
delete[] d_array;
return 0;
}

25. Указатели в С++

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

26. Указатели в С++

Задания для самостоятельной работы
Использование указателей для доступа к элементам массива
Описать одномерный массив arr из 5 элементов типа int.
1.Вывести на экран в виде arr=...значение arr (какого оно типа?), и в цикле
поочередно адреса всех элементов массива. Адрес каждого элемента выводим с
новой строки в виде &arr[...]= ... Проанализировать результаты.
2.Используя для доступа к элементам массива адресную арифметику (а не
квадратные скобки) в цикле присвоить элементам массива последовательно
значения от 1 до 5.
3.Присвоить arr адрес среднего (третьего по счету) элемента массива. Что
происходит при компиляции программы и как это можно объяснить? Строку
закомментировать.
4.Добавить в программу указатель pArr на тип int. Присвоить указателю pArr
адрес среднего элемента массива.
5.Рассматривая pArr как указатель на массив, вывести значения всех элементов. В
каких пределах должен изменяться индекс у "массива" pArr?
English     Русский Rules