Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курсовые / Язык программирования Сpp 25.09.11.doc
Скачиваний:
114
Добавлен:
10.05.2015
Размер:
10.13 Mб
Скачать

5.1.Типы указателей и операции с указателями

Указатели о которых мы говорили выше это, так называемые, указатели-переменные. Наряду с ними существуют указатели-константы. А вообще указатели делятся на две категории – указатели на объекты и указатели на функции. Здесь встретилось новое слово объект. Пока под объектом мы будем понимать все то, что не функция, т.е. это переменные любого типа, массивы и структуры. Позднее мы узнаем, что множество объектов значительно богаче. Определение указателей, как отмечалось, может быть совмещено с их инициализацией так

тип *имя_указателя = выражение;

тип *имя_указателя (выражение);

Пример

int x=1,y=2 ;

int * p1=&x , *p2=&y;

Инициализирующее выражение должно давать адрес, т.е это можни быть явно заданный адрес, уже инициализированный указатель, или выражение, позволяющее получить адрес с помощью операции &. Это значит, что над указателями могут проводиться какие то операции. Действительно, это так, однако по сравнению с операциями над базовыми типами список операций над указателями значительно беднее. Над указателями можно проводить следующие операции:

  • разыменовывание или доступ по адресу *;

  • преобразование типов;

  • присваивание;

  • получение адреса &;

  • сложение и вычитание;

  • инкремент ++;

  • декремент --;

  • операции отношений.

С некоторыми из них мы уже знакомы. Другие не на много сложнее. Рассмотрим их.

Начнем с вычитания. Вычитание применимо к указателям на объекты одного типа. Выитание указателей одного типа позволяет определить расстояние меду двумя участками, причем за единицу памяти принимается размер памяти занимаемый этим объектом. Например, есть две переменные типа double. Каждая из них занимает 8 байтов. Даже если они находятся рядом, результатом вычитания указателей будет 1. Если между ними находится еще одна переменная того же типа, то разность будет равна 2. То есть вычитание указателей не совпадает с операцией вычитания адресов.

Вот пример программы иллюстрирующей сказанное

#include <iostream>

#include <windows.h>

using namespace std;

void main(){

SetConsoleOutputCP(1251);

//=============================================

int i1=1,i2=2,*pi1,*pi2;

pi1=&i1; pi2=&i2;

cout<<"Значение указателей типа int"<<endl;

cout<<"pi1="<<pi1<<"\tpi2="<<pi2<<endl; /* «\t»-горизонтальная

табуляция */

cout<<"Разность указателей типа int"<<endl;

cout<<"pi1-pi2="<<pi1-pi2<<endl;

//=============================================

double d1=1,d2=2;

double *pd1=&d1, *pd2=&d2;

cout<<" Значение указателей типа double"<<endl;

cout<<"pd1="<<pd1<<"\tpd2="<<pd2<<endl;

cout<<" Разность указателей типа double"<<endl;

cout<<"pd1-pd2="<<pd1-pd2<<endl;

//=============================================

char ch1='a',ch2='b',*pch1,*pch2;//указатели объявлены как символы

pch1=&ch1; pch2=&ch2;

cout<<" Значение указателей типа char"<<endl;

cout<<"pch1="<<(void *)pch1<<"\tpch2="<<(void *)pch2<<endl;

cout<<" Разность указателей типа char"<<endl;

cout<<"pch1-pch2="<<pch1-pch2<<endl;

//=============================================;

bool b1=true,b2=false, *pb1=&b1,*pb2=&b2;

cout<<" Значение указателей типа bool"<<endl;

cout<<"pb1="<<pb1<<"\tpb2="<<pb2<<endl;

cout<<" Разность указателей типа bool"<<endl;

cout<<"pb1-pb2="<<pb1-pb2<<endl;

}

А вот результат

Действительно для всех базовых переменных разность указателей получилась равной 1.

Динамические переменные, как видно из рассмотренного примера, используются не только для того, чтобы программе хватило памяти. Никакой экономии при создании нескольких динамических переменных нет. Другое дело если эти переменные являются массивами. Особенно удобным является создание, так называемых, динамических массивов, т.е. массивов размер которых может быть известен только к моменту его объявления.Без применения указателей такой массив создать невозможно.

А сейчас рассмотрим еще один пример, в котором используется функция sizeof(argument).Эта функция возвращает количество байт занятых в памяти типом данных или выражением, передаваемым функции. Если передается выражение, то оно не вычисляется. Операцияsizeof обычно используется для определения необходимого объема памяти при размещении переменной операциейnew. Также она бывает необходима для определения числа элементов массива при обработке в цикле. Еслиsizeofстоит перед типом, то тип заключается в круглые скобки. Если перед переменной, то круглые скобки необязательны. Например,

int i;

cout<<sizeof(int);

cout<<sizeof i;

Итак, вот этот пример:

#include <windows>

#include <iostream>

using namespace std;

void main()

{

SetConsoleOutputCP(1251);

cout<<"Результаты различных случаев применения sizeof.\n";

cout<<"char:"<<sizeof(char)<<endl;

cout<<"char&:"<<sizeof(char&)<<endl;

cout<<"char*:"<<sizeof(char*)<<endl;

cout<<"wchar_t:"<<sizeof(wchar_t)<<endl; /* wchar_t расширенный

тип char */

cout<<"bool*:"<<sizeof(bool)<<endl;

cout<<"short*:"<<sizeof(short)<<endl;

cout<<"int:"<<sizeof(int)<<endl;

cout<<"long:"<<sizeof(long)<<endl;

cout<<"double:"<<sizeof(double)<<endl;

cout<<"long double:"<<sizeof(long double)<<endl;

enum DIGIT{ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE}; // enum –это перечисление для тех кто не знает

cout<<"DIGIT:"<<sizeof(DIGIT)<<"Member:"<<sizeof(ZERO)<<endl;

char ca[10];

cout<<"char[10]:"<<sizeof(ca)<<"элементов:"<<sizeof(ca)/sizeof(ca[0])<<endl;

double da[10];

cout<<"double[10]:"<<sizeof(da)<<"элементов:"<<sizeof(da)/sizeof(da[0])<<endl;

struct cd{

char c;

double d;

} cda[10];

cout<<"struct cd[10]:"<<sizeof(cda)<<"элементов:"<<sizeof(cda)/sizeof(cda[0])<<endl;

char *cp=new char[10];

cout<<"new char[10]:"<<sizeof(cp)<<"*cp:"<<sizeof(*cp)<<endl;

int i;

cin>>i;

}

Вот результат