К указателям могут применяться только две арифметические операции: сложение и вычитание. Для понимания арифметических действий с указателями предположим, что p1 - это указатель на целое, содержащий значение 2000, и будем считать, что целые имеют длину 2 байта. После выражения
p1 ++;
содержимое p1 станет 2002, а не 2001! Каждый раз при увеличении p1 указатель будет указывать на следующее целое. Это справедливо и для уменьшения. Например:
р1 --;
приведет к тому, что p1 получит значение 1998, если считать, что раньше было 2000.
Каждый раз, когда указатель увеличивается, он указывает на следующий элемент базового типа. Каждый раз, когда уменьшается - на предыдущий элемент. В случае указателей на символы это приводит к «обычной» арифметике. Все остальные указатели увеличиваются или уменьшаются на длину базового типа. Рис. демонстрирует данную концепцию.
Естественно, все не ограничивается только уменьшением или увеличением. Можно добавлять или вычитать из указателей целые числа. Выражение
p1 = p1 + 9;
приводит к тому, что указатель p1 указывает на девятый элемент по сравнению с элементом, на который он указывал до присваивания.
Помимо добавления или вычитания указателей и целых чисел, единственную операцию, которую можно выполнять с указателями, - это вычитание одного указателя из другого.
В большинстве случаев вычитание одного указателя из другого имеет смысл только тогда, когда оба указателя указывают на один объект, - как правило, массив. В результате вычитания получается число элементов базового типа, находящихся между указателями. Помимо этих операций не существует других арифметических операций, применимых к указателям. Нельзя умножать или делить указатели, нельзя складывать указатели, нельзя применять битовый сдвиг или маски к указателям, нельзя добавлять или вычитать типы float или double.