С указателями можно выполнять не только операции присваивания и обращения по адресу, но и ряд арифметических операций. Прежде всего, указатели одного и того же типа можно сравнивать с помощью стандартных операций сравнения. При этом сравниваются значения указателей, а не значения величин, на которые данные указатели ссылаются. Так, в приведенном ниже примере результат первой операции сравнения будет ложным:
int x = 10;int y = 10;int* xptr = &x;int* yptr = &y;// сравниваем указателиif (xptr == yptr) { cout << "Указатели равны" << endl;} else { cout << "Указатели неравны" << endl;}// сравниваем значения, на которые указывают// указателиif (*xptr == *yptr) { cout << "Значения равны" << endl;} else { cout << "Значения неравны" << endl;}
Однако результат второй операции сравнения будет истинным, поскольку переменные x и y имеют одно и то же значение.
Кроме того, над указателями можно выполнять ограниченный набор арифметических операций. К указателю можно прибавить целое число или вычесть из него целое число. Результатом прибавления к указателю единицы является адрес следующей величины типа, на который ссылается указатель, в памяти. Поясним это на рисунке. Пусть xPtr – указатель на целое число типа long, а cp – указатель на тип char. Начиная с адреса 1000, в памяти расположены два целых числа. Адрес второго — 1004 (в большинстве реализаций C++ под тип long выделяется четыре байта). Начиная с адреса 2000, в памяти расположены объекты типа char.
Рис. 9.2. Адресная арифметика.
Размер памяти, выделяемой для числа типа long и для char, различен. Поэтому адрес при увеличении xPtr и cp тоже изменяется по-разному. Однако и в том, и в другом случае увеличение указателя на единицу означает переход к следующей в памяти величине того же типа. Прибавление или вычитание любого целого числа работает по тому же принципу, что и увеличение на единицу. Указатель сдвигается вперед (при прибавлении положительного числа) или назад (при вычитании положительного числа) на соответствующее количество объектов того типа, на который показывает указатель. Вообще говоря, неважно, объекты какого типа на самом деле находятся в памяти — адрес просто увеличивается или уменьшается на необходимую величину. На самом деле значение указателя ptr всегда изменяется на число, равное sizeof(*ptr).
Указатели одного и того же типа можно друг из друга вычитать. Разность указателей показывает, сколько объектов соответствующего типа может поместиться между указанными адресами.