При работе с указателями можно также выполнять следующие операции: арифметические, сравнение, приведение типов.
Арифметические операции над указателями
Эти операции применимы только к указателям одного типа и имеют смысл только при работе со структурами данных, последовательно размещенными в памяти, например, с массивами. В любых других случаях эти операции вряд ли оправданы.
Инкремент(++). Прибавление к указателю 1 увеличивает содержащееся в нем значение на размер области памяти, отводимый объекту соответствующего типа. Фактически значение указателя меняется на величину sizeof(тип). Т.е. указатель перемещается (в случае работы с массивами) к следующему элементу массива. Если тип char занимает 1 байт, то применив к указателю на char операцию инкремент, он будет указывать на следующий байт памяти. Если это 4 – байтовый тип int, то после инкремента указатель будет указывать на следующий 4-байтовый участок памяти.
Short *pshort=new short[5];
pshort++; //значение pshort увеличиться на 2
long *qlong=new long[5];
qlong++; //значение qlong увеличиться на 4;
А здесь
int i;
int *pi=&i;
*pi++; //или *p=*p+1 - увеличение значения переменной i на 1
Декремент(--). Аналогично инкременту, но только в сторону уменьшения адреса.
Сложение (вычитание) с целой константой. Если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на величину этой константы, умноженную на размер объекта данного типа.
Разность двух указателей – это разность их значений, деленная на размер типа в байтах (в применении к массивам разность указателей на третий и шестой элементы равна 3). Суммирование двух указателей не допускается. Например, pi (указатель на int) содержит значение адреса 3000. Тогда оператор
pi=pi+2;
увеличит значение адреса с.о: 3000+2*4Байт, так как тип int занимает 4байта памяти. Если бы pi был указателем на начало массива типа int, то после выполнения той же операции pi указывал бы на третий элемент массива.
Сравнение. Указатели можно сравнивать, используя операции проверки равенства и отношения, но такое сравнение бессмысленно, если указатели не указывают на элементы одного и того же массива. При сравнении указателей сравниваются адреса, хранимые в указателях. Сравнение двух указателей, указывающих на один и тот же массив, может показать, например, что один указатель указывает на элемент массива с более высоким номером, чем другой указатель. Типичным использованием сравнения указателя является определение, равен ли указатель 0.
Замечания:
Если указатель необходимо увеличить или уменьшить на 1, то применяются операции инкремента и декремента.
Использование арифметических действий с указателями, не ссылающимися на элементы массива, обычно является логической ошибкой, т.к. мы не можем предполагать, что две переменные одинакового типа хранятся в памяти вплотную друг к другу.
Вычитание и сравнение двух указателей, которые не ссылаются на элементы одного и того же массива также является логической ошибкой.
Выход за пределы массива при использовании арифметических действий над указателями также является логической ошибкой
Операция приведения типов. Указатель можно присваивать другому указателю, если оба указателя имеют один и тот же тип. В противном случае нужно использовать операцию приведения типа, чтобы преобразовать значение указателя в правой части присваивания к типу указателя в левой части присваивания.
unsigned long int A=0Xcc77ffaa;
usigned short int *pint=(unsigned short int*) &A;
unsigned char *pchar=(unsigned char *)&A;
cout<<A<<*pint<<*pchar;
Этот пример выведет на экран строку:
Cc77ffaa ffaa aa
Значения указателей pint и pchar одинаковы, однако разадресация дает разный результат: для pchar – один младший байт, для pint – два младших байта. При инициализации указателей была использована операция явного приведения типа: перед именем переменной в скобках указывается тип, к которому ее требуется преобразовать. При этом не гарантируется сохранение информации. И вообще, такой оператор приведения типа является устаревшим, хотя допускается стандартом С++. Но сами разработчики С++ не рекомендуют использовать эту устаревшую форму. Операторы явного преобразования типов, введенные в С++, будут рассмотрены позже.