Адресная арифметика
С указателями можно выполнять следующие операции: разадресация, или косвенное обращение к объекту (*), присваивание, сложение с константой, вычитание, инкремент (++), декремент (--), сравнение, приведение типов. При работе с указателями часто используется операция получения адреса (&). В языке С/С++ допустимы только две арифметические операции над указателями: сложение и вычитание. Арифметические операции с автоматически учитывают размер типа величин, адресуемых указателям. Эти операции применимы только к указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например, с массивами.
Инкремент перемещает указатель к следующему элементу массива, декремент - к предыдущему. Фактически значение указателя изменяется на величину sizeof(тип). Если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на эту величину этой константы, умноженную на рамер объекта данного типа, например: short * p = new short [5]; p++; //значение p увеличивается на 2 long * q = new long [5]; q++; //значение q увеличивается на 4 Операции адресной арифметики подчиняются следующим правилам. 1) Допустимые операции с указателями – инкремент, декремент, прибавление или вычитание целого числа к указателю. 2) После выполнения операции увеличения над указателем, данный указатель будет ссылаться на следующий объект своего базового класса. 3) После выполнения операции уменьшения над указателем, данный указатель будет ссылаться на предыдущий объект своего базового класса. 4) Для всех указателей (всех типов) адрес увеличивается или уменьшается на величину, равную размеру объекта того типа, на который они указывают. Пример. Выполнение оператора pi = pi +1; «передвигает» указатель на 1 объект в сторону увеличения адреса. Выполнение pch +=4; «передвигает» указатель на 4 объект в сторону увеличения адреса. В итоге, адреса pi +1 и pch +4 совпадают. char *pch = (char *)1000; int *pi = (int *)1000;
Рис. 2. Адресная арифметика Ещё одна операция – можно вычитать два указателя одного типа. Благодаря этому, можно определить количество объектов, расположенных между адресами, на которые указывают данные указатели. Разность двух указателей – это разность их значений, деленная на размер типа в байтах (в применении к массивам разность указателей, например, на третий и шестой элементы равна 3). Суммирование двух указателей не допускается.
При записи выражений с указателями следует обращать внимание на приоритеты операций. В качестве примера рассмотрим последовательность действий заданную в операторе *p++ = 10; Операции разадресации и инкремента имеют одинаковый приоритет и выполняются справа налево, но, поскольку инкремент постфиксный, он выполняется после выполнения операции присваивания. Таким образом, сначала по адресу, заданному в указателе p, будет записано значение 10, а затем указатель будет увеличен на количество байт, соответствующее его типу. То же самое можно записать подробнее: *p = 10; p++; Выражение (*p)++, напротив, инкрементирует значение, на которое ссылается указатель.
|