Указатели
Для большинства типов T указатель на T имеет тип T*. Это значит, что переменная типа T* может хранить адрес объекта типа T. Указатели на массивы и функции, к сожалению, требуют более сложной записи:
int* pi;
char** cpp; // указатель на указатель на char
int (*vp)[10]; // указатель на массив из 10 целых
int (*fp)(char, char*); // указатель на функцию с параметрами
// char и char*, возвращающую int
Главная операция над указателями - это косвенное обращение (разыменование), т.е. обращение к объекту, на который настроен указатель. Эту операцию обычно называют просто косвенностью. Операция косвенности * является префиксной унарной операцией. Например:
char c1 = 'a';
char* p = &c1; // p содержит адрес c1
char c2 = *p; // c2 = 'a'
Переменная, на которую указывает p,- это c1, а значение, которое хранится в c1, равно 'a'. Поэтому присваиваемое c2 значение *p есть 'a'. Над указателями можно выполнять и некоторые арифметические операции. Ниже в качестве примера представлена функция, подсчитывающая число символов в строке, заканчивающейся нулевым символом (который не учитывается):
int strlen(char* p)
{
int i = 0;
while (*p++) i++;
return i;
}
Можно определить длину строки по-другому: сначала найти ее конец, а затем
вычесть адрес начала строки из адреса ее конца.
int strlen(char* p)
{
char* q = p;
while (*q++) ;
return q-p-1;
}
Широко используются указатели на функции; они особо обсуждаются
в $$4.6.9