Этот шаг посвящен изложению действий, которые можно выполнять над
указателями.
Вначале заметим, что ни один "правильный" указатель не может иметь значения 0, поэтому равенство нулю значения указателя может служить сигналом о ненормальном завершении выполнения функции.
Над указателями можно выполнять следующие операции:
Приведем несколько примеров.
Например:
Проиллюстрируем использование этих операций конкретными примерами.
#include <iostream.h> void main() { unsigned long L=0x12345678L; char *cp=(char *)&L; int *ip=(int *)&L; long *lp=(long *)&L; cout << hex; //Шестнадцатеричное представление выводимых значений. cout << "\n Адрес L, &L=" << &L; cout << "\ncp = " << (void*)cp << "\t*cp = 0x" << (int)*cp; cout << "\nip = " << (void *)ip << "\t*ip=0x" << *ip; cout << "\nlp = " << (void *)lp << "\t*lp=0x" << *lp; }
Результат работы программы:
Адрес L, &L=0x243f2256 cp = 0x243f2256 *cp= 0x78 ip = 0x243f2256 *ip= 0x5678 lp = 0x243f2256 *lp= 0x12345678
В программе используется явное приведение типов. Так как адрес &L имеет тип unsigned long *, то при инициализации указателей его значение явно преобразуется соответственно к типам char *, int *, long *. При выводе значений указателей они преобразуются к типу void *, так как требуется вывод значений, а не длин участков памяти, связанных со значениями указателей.
При выводе значения *cp использовано явное преобразование типа (int), так как при его отсутствии будет выведен не код, а соответствующий ему символ ASCII-кода. Особенность размещения чисел в памяти компьютера заключается в том, что сначала размещаются младшие байты числа, а затем старшие (рис.1):
Рис.1. Схема размещения в памяти значения переменной
L
#include <iostream.h>
void main()
{
char *pac,*pbc;
long *pal,*pbl;
cout << hex;
cout << "\n Адреса указателей:";
cout << "\n &pac = " << &pac << " &pbc = " <<&pbc;
cout << "\n &pal = " << &pal << " &pbl = " <<&pbl;
cout << "\n Длины указателей некоторых типов:";
cout << "\n sizeof (void *) = " << sizeof(void *);
cout << "\n sizeof (char *) = " << sizeof(char *);
cout << "\n sizeof (int *) = " << sizeof(int *);
cout << "\n sizeof (long *) = " << sizeof(long *);
cout << "\n sizeof (float *) = " << sizeof(float *);
cout << "\n sizeof (double *) = " << sizeof(double *);
cout << "\n sizeof (long double *) = " << sizeof(long double *);
}
Результат работы программы:
Адреса указателей: &pac = 0x5cff2314 &pbc = 0x5cff2310 &pal = 0x5cff230c &pbl = 0x5cff2308 Длины указателей некоторых типов: sizeof (void *) = 4 sizeof (char *) = 4 sizeof (int *) = 4 sizeof (long *) = 4 sizeof (float *) = 4 sizeof (double *) = 4 sizeof (long double *) = 4
#include <iostream.h> void main() { int i1=10, i2=20, i3=30; int *p=&i2; //Значение i2. cout << "\n *&i2 = " << *&i2; //Значение i2 сначала увеличенное на 1. cout << "\n *&++i2 = " << *&++i2; //Значение i2. cout << "\n *p = " << *p; //Значение i2, p увеличивается на 1. cout << "\n *p++ = " << *p++; //Значение i1. cout << "\n *p = " << *p; //Значение i1 сначала увеличенное на 1. cout << "\n ++*p = " << ++*p; //Значение i2, сначала уменьшается p. cout << "\n*--p = " << *--p; //Значение i3, сначала уменьшается p, затем полученное значение i3 //увеличивается. cout << "\n++*--p = " << ++*--p; }
Результат работы программы:
*&i2 = 20 *&++i2 = 21 *p = 21 *p++ = 21 *p = 10 ++*p = 11 *--p = 21 ++*--p = 31
Выражение *p++ вычисляется в таком порядке: вначале выполняется
именование
(обращение по адресу), и полученное значение (21) служит значением выражения
в целом.
Затем выполняется операция ++ и значение указателя увеличивается на 1. Тем
самым он
"устанавливается" на переменную i1. (В памяти компьютера
переменные i1,i2, i3
располагаются в обратном порядке).
На следующем шаге мы поговорим об операции sizeof.