Операции над указателями. Помимо уже рассмотренных операций, с указателями можно выполнять арифметические операции сложения, инкремента (++)
Помимо уже рассмотренных операций, с указателями можно выполнять арифметические операции сложения, инкремента (++), вычитания, декремента (--) и операции сравнения.
Арифметические операции с указателями автоматически учитывают размер типа величин, адресуемых указателями. Эти операции применимы только к указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например с массивами.
Инкремент перемещает указатель к следующему элементу массива, декремент – к предыдущему.
Указатель, таким образом, может использоваться в выражениях вида
p # iv, ## p, p ##, p # = iv,
p – указатель, iv – целочисленное выражение, # – символ операции '+' или '–'.
Результатом таких выражений является увеличенное или уменьшенное значение указателя на величину iv * sizeof(*p), т.е. если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на величину этой константы, умноженную на размер объекта данного типа.
Текущее значение указателя всегда ссылается на позицию некоторого объекта в памяти с учетом правил выравнивания для соответствующего типа данных. Таким образом, значение p # iv указывает на объект того же типа, расположенный в памяти со смещением на iv позиций.
При сравнении указателей могут использоваться отношения любого вида («>», «<» и т.д.), но наиболее важными видами проверок являются отношения равенства и неравенства («==», «!=»).
Отношения порядка имеют смысл только для указателей на последовательно размещенные объекты (элементы одного массива).
Разность двух указателей дает число объектов адресуемого ими типа в соответствующем диапазоне адресов, т.е. в применении к массивам разность указателей, например, на третий и шестой элементы равна 3.
Очевидно, что уменьшаемый и вычитаемый указатели должны принадлежать одному массиву, иначе результат операции не имеет практической ценности и может привести к непредсказуемому результату. То же можно сказать и о суммировании указателей.
Значение указателя можно вывести на экран с помощью функции printf, используя спецификацию %p (pointer), результат выводится в шестнадцатеричном виде.
Рассмотрим фрагмент программы:
int a = 5, *p, *p1, *p2;
p = &a;
p2 = p1 = p;
++p1;
p2 += 2;
printf(“a = %d , p = %d , p = %p , p1 = %p , p2 = %p .\n”, a, *p, p, p1, p2);
Результат может быть следующим:
a = 5 , *p = 5 , p = FFF4 , p1 = FFF6, p2 = FFF8 .
Графически это выглядит следующим образом (в 16-разрядном процессоре на тип int отводится 2 байта):
FFF5 | FFF7 | FFF9 | |||||||
FFF4 р | FFF6 p1 | FFF8 p2 | FFF10 | ||||||
p = FFF4,
p1 = FFF6 = ( FFF4 + 1*sizeof(*p)) ® FFF4 + 2 (int)
р2 = FFF8 = ( FFF4 + 2*sizeof(*p)) ® FFF4 + 2*2
На одну и ту же область памяти (как видно из приведенного примера), может ссылаться несколько указателей различного типа. Но примененная к ним операция разадресации даст разные результаты.
При смешивании в выражении указателей разных типов явное преобразование типов требуется для всех указателей, кроме void*.
Явное приведение типов указателей позволяет получить адрес объекта любого типа:
type *p;
p = (type*) &object;
Значение указателя p позволяет работать с переменной object как объектом типа type.
Дата добавления: 2015-09-11; просмотров: 713;