Производные типы. Тип указатель: указатели на объекты
Способы инициализации указателя
- Присваивание указателю адреса области памяти существующего объекта:
- с помощью операции получения адреса:
int a=5; int *p=&a;
- с помощью проинициализированного указателя
int *r=p;
- с помощью операции получения адреса:
- Присваивание указателю адреса области памяти в явном виде:где 0х В800 0000 – шестнадцатеричная константа, ( char* ) – операция приведения типа.
char *cp=(char*)0х В800 0000;
- Присваивание указателю пустого значения:
int *N=NULL; или int *N=0;
Спецификатор указателя при форматированном выводе
Если на экран необходимо вывести адрес, следует применять спецификатор %p.
Этот спецификатор формата заставляет функцию printf() выводить на экран адрес, формат которого совместим с типом адресации, принятой в компьютере.
Операции с указателями
С указателями можно выполнять следующие операции:
- разыменование (*) – получение значения величины, адрес которой хранится в указателе;
- взятие адреса (&);
- присваивание;
- арифметические операции
- сравнение;
- приведение типов.
Пример 1. Демонстрация ситуации, когда указатели различных типов указывают на одно и то же место в памяти. Однако при разыменовании получаются разные результаты.
// Выбор данных из памяти с помощью разных указателей
// Использование функций приведения типов
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
unsigned long L=12345678;
char *cp=(char*)&L;
int *ip=(int*)&L;
long *lp=(long*)&L;
cout <<"\n&L = "<<&L;
cout <<"\nL = "<<L;
cout <<"\n*cp = "<<*cp;
cout <<"\n*ip = "<<*ip;
cout <<"\n*lp = "<<*lp;
system("pause");
return 0;
}Пример 2.
//Операции над указателями
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
int a,c,b;
int *ca, *cb;
int *sa, *sb, *sc;
cout << "a = "; cin >> a;
cout << "b = "; cin >> b;
c=a+b;
sb=&b;//инициализация указателей через взятие адреса
sa=&a;
sc =&c;
//присваивание указателю значения выражения
*sc = c+a-b;
ca=sa;//присваивание указателю значения другого указателя
cb=sb;
*sa=12;//присваивание указателю значения константы
cout << "\n*ca = " << *ca;
cout << "\n*sa = " << *sa;
cout << "\n*cb = " << *cb;
cout << "\n*sb = " << *sb;
cout << "\n*sc = " << *sc;
cout << "\nca = " << ca;
cout << "\ncb = " << cb;
cout << "\nsc = " << sc;
cout << "\na = " << a;
cout << "\nb = " << b;
cout << "\nc = " << c;
cout << "\n&a = " << &a;
cout << "\n&b = " << &b;
cout << "\n&c = " << &c;
cout << "\n*&a = " << *&a;
cout << "\n*cb-*ca = " << *cb-*ca;
cout << "\n*cb+*ca = " << *cb+*ca;
*cb+=2; //сложение с константой
cout << "\ncb = " << cb;
cb++; //инкремент
cout << "\ncb = " << cb;
ca--; //декремент
cout << "\ncа = " << ca;
cout << "\ncb-ca = " << cb-ca;
system("pause");
return 0;
}Указатели одного и того же типа можно сравнивать с помощью стандартных операций сравнения. При этом сравниваются значения указателей, а не значения величин, на которые данные указатели ссылаются.
Пример 3.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
int x=10;
int y=10;
int *xptr=&x;
int *yptr=&y;
//сравниваем указатели
if (xptr == yptr)
cout << "Указатели равны\n";
else
cout << "Указатели неравны\n";
//сравниваем значения, на которое указывает указатель
if (*xptr == *yptr) {
cout << "Значения равны\n";
} else {
cout << "Значения неравны\n";}
system("pause");
return 0;
}В приведенном примере результат первой операции сравнения будет ложным, а второй – истинным, поскольку переменные x и y имеют одно и то же значение.
Ключевые термины
Адрес объекта – это адрес области оперативной памяти, по которому хранится объект в соответствии с особенностями представления типа.
Инициализация указателя – это определение значения указателя.
Косвенная адресация – это обращение к области памяти не напрямую, по адресу, а через объект, которому в памяти соответствует определенный участок.
Непосредственно производные типы – это типы, которые являются производными от некоторых существующих типов, реализуя типы указателей, ссылки, функции преобразования типов.
Переименование типов – это задание нового имени для существующего типа.
Производные типы данных – это типы, полученные на основе более простых базовых типов.
Разыменование – это операция получения значения объекта, адрес которого хранится в указателе;
Составные производные типы – это типы, являющиеся производными от различных существующих или ранее объявленных типов.
Указатель – это именованный объект, предназначенный для хранения адреса области памяти.
Указатель на константу – это указатель на такой объект, значение которого нельзя изменить в процессе выполнения программы.
Указатель-константа – это указатель, значение которого нельзя изменить в процессе выполнения программы.
Указатель-константа на константу – это указатель, для которого невозможно изменение как самого указателя, так и значения адресуемого объекта.
Краткие итоги
- В языке С++ производные типы данных классифицируют в зависимости от построения на производные и непосредственно производные.
- Для экономии памяти и времени, затрачиваемого на обращение к данным, в программах используют указатели на объекты.
- Указатель не является самостоятельным типом, он всегда связан с другим типом.
- Указатель может быть константой или переменной, а также указывать на константу или переменную.
- Указатель типа void указывает на область памяти любого размера. Разыменование такого указателя необходимо проводить с операцией приведения типов.
- До первого использования в программе объявленный указатель необходимо проинициализировать.
- С помощью указателей можно выполнять косвенную адресацию объектов.
- Над указателями определены операции: разыменование, взятие адреса, декремент, инкремент, увеличение (уменьшение) на целую константу, разность, определение размера.
- Над указателями определены операции сравнения.
