close

Вход

Забыли?

вход по аккаунту

?

Указатели

код для вставкиСкачать
Указатели.
Как правило, при обработке оператора объявления переменной тип
имя_переменной, компилятор автоматически выделяет память под
переменную имя_переменной в соответствии с указанным типом.
Доступ к значению переменной можно получить иным способом —
определить собственные переменные для хранения адресов памяти.
Такие переменные называют указателями.
С помощью указателей можно обрабатывать массивы, строки и
структуры, создавать новые переменные в процессе выполнения
программы, передавать адреса фактических параметров.
Указатель — это переменная, значением которой является адрес
памяти, по которому хранится объект определенного типа (другая
переменная). Например, если C - это переменная типа char, а P указатель на C, значит в P находится адрес, по которому в памяти
компьютера хранится значение переменной C.
Указатель – это производный тип, который представляет
собой адрес какого-либо значения.
В языке Си++ используется понятие адреса переменных. Работа
с адресами досталась Си++ в наследство от языка Си.
Предположим, что в программе определена переменная типа int:
int x;
Можно определить переменную типа " указатель " на целое число:
int* xptr;
и присвоить переменной xptr адрес переменной x:
xptr = &x;
Операция &, примененная к переменной, – это операция
взятия адреса.
Операция *, примененная к адресу, – это операция обращения по
адресу .
Таким образом, два оператора эквивалентны:
int y = x;
// присвоить переменной y значение x
int y = *xptr; // присвоить переменной y значение,
// находящееся по адресу xptr
Операции * и & при работе с указателями
Операция получения адреса обозначается знаком &,
а операция разадресации *. Первая возвращает адрес своего операнда.
Например
:
Операция разадресации * возвращает значение переменной,
хранящееся в по заданному адресу, то есть выполняет действие,
обратное операции &:
Присваивание указателей
Значение одного указателя можно присвоить другому. Если указатели одного типа, то
для этого применяют обычную операцию присваивания . Рассмотрим ее на примере:
В данной программе определены: вещественная переменная PI=3.14159 и два указателя на
тип float - p1 и p2. В указатели записывается адрес переменной PI. В результате работы
программы в переменных p1 и p2 будет хранится значение одного и того же адреса, по
которому хранится вещественная переменная PI=3.14159.
Результат работы программы:
С помощью операции обращения по адресу можно записывать значения:
*xptr = 10; // записать число 10 по адресу xptr.
После выполнения этого оператора значение переменной x станет равным 10,
поскольку xptr указывает на переменную x.
Указатель – это не просто адрес, а адрес величины определенного типа.
Указатель xptr – адрес целой величины. Определить адреса величин других
типов можно следующим образом:
unsigned long* lPtr; // указатель на целое число без знака
char* cp; // указатель на байт
Complex* p; // указатель на объект класса Complex
Если указатель ссылается на объект некоторого класса, то операция обращения
к атрибуту класса вместо точки обозначается " -> ", например p->real.
Если вспомнить один из предыдущих примеров:
void Complex::Add(Complex x)
{
this->real = this->real + x.real;
this->imaginary = this->imaginary + x.imaginary;
}
то this – это указатель на текущий объект, т.е. объект, который выполняет
метод Add. Запись this-> означает обращение к атрибуту текущего объекта.
Можно определить переменную типа указатель на функцию и вызывать
эти функции не напрямую, а косвенно, через указатель:
int (*functptr)(long x);
functptr = &foo;
(*functptr)(2);
functptr = &bar;
(*functptr)(4);
Для чего нужны указатели?
Указатели появились, прежде всего, для нужд системного
программирования. Поскольку язык Си предназначался для
"низкоуровневого" программирования, на нем нужно было обращаться,
например, к регистрам устройств. У этих регистров вполне
определенные адреса, т.е. необходимо было прочитать или
записать значение по определенному адресу.
Благодаря механизму указателей, такие операции не требуют никаких
дополнительных средств языка.
int* hardwareRegister =0x80000; *hardwareRegister =12;
Однако
использование
указателей
программирования не ограничивается.
нуждами
системного
Указатели позволяют существенно упростить и ускорить ряд операций.
Предположим, в программе имеется область памяти для хранения
промежуточных результатов вычислений. Эту область памяти используют
разные модули программы. Вместо того, чтобы каждый раз при
обращении к модулю копировать эту область памяти, мы можем
передавать указатель в качестве аргумента вызова функции, тем самым
упрощая и ускоряя вычисления.
Упомянутые примеры использования указателей никак не связаны с
объектно-ориентированным
программированием.
Казалось
бы,объектно-ориентированное программирование должно уменьшить
зависимость от низкоуровневых конструкций типа указателей. На самом
деле программирование с классами нисколько не уменьшило
потребность в указателях, и даже наоборот, нашло им дополнительное
применение, о чем мы будем рассказывать по ходу изложения.
Над адресами в C++ определены следующие арифметические операции:
•
сложение и вычитание указателей с константой;
•
вычитание одного указателя из другого;
•
инкремент;
•
декремент;
Сложение и вычитание указателей с константой n означает, что указатель
перемещается по ячейкам памяти на столько байт, сколько занимает n
переменных того типа, на который он указывает.
Допустим, что указатель имеет символьный тип и его значение равно 100.
Результат сложения этого указателя с единицей — 101, так как для хранения
переменной типа char требуется 1 байт.
Если же значение указателя равно 100, но он имеет целочисленный тип, то
результат его сложения с единицей будет составлять 104, так как для переменной
типа int отводится 4 байта.
Вычитание двух указателей определяет, сколько переменных данного типа
размещается между указанными ячейками. Эти операции применимы только к
указателям одного типа и имеют смысл в основном со структурными типами
данных, например с массивами.
Фактически получается, что значение указателя изменяется на
величину
sizeof(тип).
Если
указатель
на
определенный
тип увеличивается или уменьшается на константу, то его значение
изменяется на величину этой константы, умноженную на размер объекта
данного типа. Например:
Разность двух указателей - это разность их значений, деленная на размер типа
в байтах. Так, разность указателей на третий и нулевой элементы массива равна
трем, а на третий и девятый — шести. Суммирование двух указателей не
допускается.
Инкремент перемещает указатель к следующему элементу массива, а
декремент - к предыдущему:
К указателям так же применимы операции отношения ==, !=, <,>,<=,>=.
Иными словами, указатели можно сравнивать.
Например, если i указывает на пятый элемент массива, а j — на первый, то
отношение i>j истинно.
Кроме того, любой указатель можно сравнивать на равенство с нулем.
Однако, все эти утверждения верны, если речь идет об указателях, ссылающихся на
один массив. В противном случае результат арифметических операций и операций
отношения будет не определен.
Документ
Категория
Презентации
Просмотров
129
Размер файла
226 Кб
Теги
указатели, презентация
1/--страниц
Пожаловаться на содержимое документа