На этом шаге мы рассмотрим это понятие.
Указатель - это переменная, которая содержит адрес другой переменной (говорят, что указатель указывает на переменную того типа, адрес которой он содержит). Существует одноместная (унарная, т. е. для одного операнда) операция взятия адреса переменной &.
Если имеем объявление int а, то можно определить адрес этой переменной &а. Если pа - указатель, который будет указывать на переменную типа int, то можем записать: pа=&а.
Существует унарная операция * (она называется операцией разыменования), которая воздействует на переменную, содержащую адрес объекта (т. е. на указатель). При этом извлекается содержимое переменной, адрес которой находится в указателе. Если, как мы видели, pа=&а, то, воздействуя на обе части операцией *, получим (по определению этой операции): *pа=а;.
Исходя из этого, указатель объявляется так:
<тип переменной>* <имя указателя>
Здесь:
Это и есть правило объявления указателя: указатель на переменную какого-то типа - это такая переменная, при воздействии на которую операцией разыменования получаем значение переменной этого же типа.
Прежде чем использовать указатель, его необходимо инициализировать, т. е настроить на какой-то конкретный объект. Указатель может иметь нулевое значение, гарантирующее, что он не совпадает ни с одним значением указателя, используемого в данный момент в программе. Если мы присвоим указателю константу 0, то получим указатель с нулевым значением. Такой указатель можно сравнивать с мнемоническим NULL, определенным в стандартной библиотеке stdio.h.
Указатель может иметь тип void, т. е. указывать на "ничто", но указатель этого типа нельзя путать с нулевым.
Объявление:
void *ptr;
Примером указателя типа void может служить функция malloc(), возвращающая указатель на динамическую область памяти, выделяемую ею под объект. Она возвращает указатель типа void, и пользователь должен сделать приведение (casting) этого типа к типу объекта методом принудительного назначения типа (в скобках указать тип).
Если, например, мы выделили память под объект типа char, то надо объявить:
char object[]; char *p=(char *)malloc(sizeof(object));
Пусть некоторый указатель pс указывает на переменную типа char, т. е. содержит адрес места памяти, начиная с которого располагается объект типа char (например, строка символов).
Объявление такого указателя по определению будет выглядеть так:
char* рc;
Теперь воздействуем на него операцией разыменования. Получим *pc. Это будет значение первого символа строки, на начало которой указывал указатель. Чтобы получить значение следующего символа строки, надо указатель увеличить на единицу: pс++ и применить *(pс++).
Вообще, какого бы типа не был объект, на начало которого в памяти указывает некоторый указатель р (а он указывает именно на начало объекта в памяти, когда говорят, что он указывает на объект), p++ всегда указывает на следующий элемент объекта, p+i - на i-й элемент. Приращение адреса, который содержит указатель р, всегда сопровождается масштабированием размера памяти, занимаемого элементом объекта.
Дополнительную информацию по указателям можно получить здесь.
На следующем шаге мы рассмотрим особенности использования указателей в среде Microsift Visual C++.