
ЯиМП Лекция 4_C_Указатели.ppt
- Количество слайдов: 32
Лекция 4. C. Указатели. Работа с указателями. Языки и методы программирования. М. А. Сокольская
План. 1. 2. 3. 2 Динамические переменные. Указатели. Операторы для работы с указателями. Выражения, содержащие указатели.
Виды переменных 3 Статические переменные – автоматически создаваемые в начале исполнения блока программы и уничтожаемые по окончании работы блока. Размещение в памяти – на этапе трансляции. Динамические переменные. Переменные, выделение и очистка памяти для которых происходит в процессе выполнения программы.
Динамические переменные используются, если: размер необходимой структуры заранее неизвестен структура может видоизменяться в процессе работы программы. В языке С++ динамические переменные реализованы через указатели. 4
Указатели Определение: Указатель (pointer) – это переменная, в которой хранится адрес другого объекта (как правило другой переменной). Т. е. значением переменной-указателя является адрес ячейки памяти, в которой содержится динамическая величина. 5
Объявление указателей Переменная, хранящая адрес ячейки памяти должна быть объявлена как указатель в разделе объявления переменных. Синтаксис: тип_указателя *имя_указателя 6 Тип указателя – это базовый тип указателя (любой допустимый тип).
Пример int main (void) { double x=10. 5, y; int *p; char *p 1; … } Если переменная занимает несколько ячеек памяти, то ее адресом считается адрес первой ячейки. 7
Операторы для работы с указателями Существует два специальных оператора для работы с указателями. & - оператор получения адреса. p = &count; //присвоить указателю p адрес //переменной count * - оператор разыменования указателя. 8 q = *p; //значение, хранящееся по адресу p //присвоить q
Приоритет операторов * и & выше приоритета всех арифметических операторов. При использовании указателей необходимо следить за тем, чтобы указатель всегда ссылался на переменную правильного типа (не всякий компилятор отслеживает такие ошибки). 9
Пример. 10 #include <iostream. h> int main (void) { double x=5. 6, y; int n; int *p, *p 1; p = &n; //верная запись p 1 = &x; //нежелательная запись y = *p 1; cout<< y; //не выведет число 5, 6 return 0; }
Выражения, содержащие указатели Обычно, выражения, содержащие указатели, подчиняются стандарту, но у них есть свои особенности. Особенности проявляются в случаях: - присваивания указателей. - адресной арифметики - сравнения указателей 11
Присваивание указателей 12 Указатель можно присвоить другому указателю. Пример. #include <iostream. h> int main (void) { int x; int *p 1, *p 2; p 1 = &x; p 2 = p 1; cout<< p 2; //выведет на экран адрес переменной x return 0 }
Адресная арифметика 13 К указателям применимы только две арифметических операции: сложение вычитание Пример. Пусть указатель p 1 ссылается на целочисленную переменную, размещенную по адресу 2000. Пусть целые числа занимают 2 байта в памяти. p 1++; Чему будет равно значение p 1?
p 1 будет равно 2002, т. к. указатель будет ссылаться на следующее целое число. Выражение p 1 --; присвоит указателю p 1 снова значение 2000. 14
Правила адресной арифметики. 15 1. При увеличении на 1 указатель ссылается на ячейку, в которой хранится следующий элемент базового типа. 2. При уменьшении на 1 указатель ссылается на ячейку, в которой хранится предыдущий элемент базового типа. 3. В целом указатели увеличиваются или уменьшаются на длину соответствующих переменных, на которые они ссылаются. 4. Указатели можно вычитать.
Сравнение указателей Указатели можно сравнивать между собой. Пример. if (p<q) cout <<“Указатель p содержит меньший адрес, чем указатель q”; 16 Указатели сравниваются, если они ссылаются на один и тот же объект (например массив) для контроля размерности или переполнения конструкции
Пример. Функции для работы со структурой типа стек. #include <iostream> #include <stdlib. h> int *top, *p 1, stack [50]; int main (void) { int value; //значение для размещения в стеке top = stack; //указатель ссылается на вершину стека p 1 = stack; //инициализация указателя p 1 17
do { cout<<“Введите число: “; cin>>value; if (value!=0) { p 1++; if (p 1 == (top + SIZE)) { cout<< “Стек переполнен. “; exit (1); } 18
*p 1 = value; //записать значение value в //адрес, хранимый в p 1 } else { 19 if (p 1 == top) { cout<<Стек исчерпан. ; exit (1); }
p 1 --; //уменьшаем указатель на 1 //(переводим к предыдущему элементу) cout<<“Число на вершине стека равно”<< *(p 1+1)<<endl; } } while (value!=-1); return 0 } 20
Косвенная адресация Указатель ссылается на другой указатель, который содержит адрес обычной переменной. Такая схема называется косвенной адресацией или указателем на указатель. Минус: снижение наглядности программы. Глубина косвенной адресации не ограничена. 21
22
Объявление переменной Переменная, представляющая собой указатель на указатель объявляется следующим образом: базовый_тип **имя_указателя; Например: double **point; 23
Извлечение значения в косвенной адресации Если переменная объявлена как указатель на указатель, то для извлечения значения дважды применяется оператор разыменования. 24
Пример 25 #include <stdio. h> int main() { int x, *p, **q; x=10; p=&x; q=&p; printf (“%d”, **q); //вывод числа x return 0; }
Инициализация указателей Если указатель объявлен, но не инициализирован, то его значение остаётся неопределённым. Эта ситуация может приводит к непредсказуемым последствиям. Указатель, не ссылающийся на конкретную ячейку памяти должен быть равен нулю. int *s; s=0; или s=NULL; Часто инициализируются строки. 26
Динамическое распределение памяти Получение программой необходимой памяти в процессе её выполнения. Память, выделяемая при распределении находится в куче (heap), которая представляет собой область свободной памяти между кодом программы, сегментом данных и стеком. Размер кучи заранее неизвестен. 27
Динамическое распределение памяти 28 Выделение памяти. Оператор new выделяет область памяти и возвращает указатель на ее первую ячейку. указатель = new тип; Например: int *s; s = new int; Оператор delete применяется только к результату оператора new.
Освобождение памяти. Оператор delete освобождает память, выделенную с помощью оператора new. delete указатель; Например: int *s; s = new int; //работа с указателем s delete s; 29
Проблемы при работе с указателями Неинициализированный указатель. int main() { int x, *p; x=10; *p=x; return 0; } Число 10 записывается в неизвестную область памяти. 1. 30
2. Неправильная работа с указателями. int x, *p; x = 10; p = x; printf (“%d”, *p); Неверное присваивание p=x, поэтому непредсказуемое значение на экране. 31
Итоги Мы рассмотрели понятие указателя, операторы работы с указателями, принципы интерпретации выражений, содержащих указатели. 32
ЯиМП Лекция 4_C_Указатели.ppt