Механизм указателей одна из наиболее привлекательных для программистов особенностей языка Си, который позволяет получить доступ к адресам ячеек оперативной памяти.
Указатель-константа – это значение адреса ячейки в 16-чной системе счисления.
Указатель-переменная (просто указатель) – это переменная, которая может хранить адрес другого объекта программы. Доступ к объекту теперь обеспечивается теперь не прямо через имя переменной, а косвенно, через указатель, хранящий адрес этой переменной. Для описания указателя-переменной используется модификатор * перед этой переменой, как особый тип данных “указатель на что-либо”:
int var, *ptr; /* переменная и указатель на объект целого типа */
Определены две специальные операции для работы с переменными через указатели: операция & (получение адреса объекта) и операция * (разадресация, косвенный доступ к содержимому ячейки через указатель на нее). Кроме того доступны арифметические операции с указателями (как целыми величинами) и операции присваивания.
Пример.
float var=5.1, *ptr; /* переменная и указатель вещественного типа */
ptr = &var; /* получение адреса var и запись его в указатель */
*ptr = *ptr+2.5; /* изменение var косвенно, через указатель */
printf (“var=%f”, var); /* результат var = 7.6 */
В Си существует непосредственная связь между указателями и массивами, поскольку имя массива является указателем-константой, то есть адресом элемента с индексом 0 (точнее адресом первого байта этого элемента).
Пример. Пусть данные описания:
int ar [4], *ptr; /* массив и указатель на объект целого типа */
Пусть элементы массива размещены в памяти, начиная с байта с адресом 100:
Элементы: | ar [0] | ar [1] | ar [2] | ar [3] | ||||
Байты памяти: | ||||||||
Адреса байтов: | ||||||||
Адреса элементов: | &ar[0] | &ar[1] | &ar[2] | &ar[3] | ||||
Указатели: | ar | ar+1 | ar+2 | ar+3 | ||||
Таким образом ar+i = &ar[i] (в частности ar=&a[0]), поскольку адрес элемента вычисляется по формуле:
адрес элемента = имя массива + индекс * sizeof(тип массива),
где функция sizeof (тип) определяет размер элемента в байтах.
Поскольку имя массива является указателем-константой, его нельзя изменить оператором присваивания вида ar= выражение, но им можно инициировать при описании указатель-переменную, например,
int ar[4], *ptr=ar;
либо присвоить имя массива указателю-переменной:
ptr = ar;
либо получить адрес массива в 16-й системе счисления:
printf (“Адрес массива ar=%x”, ar).
Адресное выражение образуется на основе имени массива или указателя на массив, например,
ar+i, ptr+i или i+ar, i+ptr.
Доступ к элементам массива через адресное выражение осуществляется с помощью операции * (разадресации): *(ar+i) или *(ptr+i).