Шрифт:
Мы уже использовали в предыдущих программах оператор & при обращении к scant. Этот унарный оператор, который называют адресным (address) опе-ратором, создает указатель на переменную в Objective-C. Например, если х — переменная определенного типа, то выражение &х является указателем на эту переменную. Если нужно, вы можете присвоить выражение &х любой перемен-ной-указателю, объявленной как указатель на тип, который имеет переменная х. Оператор intPtr = &count;
задаст косвенную связь между intPtr и count. Адресный оператор 8 присваивает переменной intPtr не значение переменной count, а указатель на переменную count. На рис. 13.1 показана связь между intPtr и count. Линия со стрелкой показывает, что intPtr содержит не само значение count, а указатель на переменную count.
Рис. 13.1. Указатель на переменную целого типа
Чтобы указать содержимое count с помощью переменной-указателя intPtr, ис-пользуется оператор косвенного обращения «звездочка» (*). Если переменная х была определена с типом int, то оператор х = *intPtr;
присвоит переменной х значение, которое указывается путем косвенного обра-щения через intPtr. Поскольку выше мы задали, что intPtr указывает на переменную count, результатом этого оператора будет присваивание переменной х значения, содержащегося в переменной count (10).
В программе 13.8 показано использование двух основных операторов для указателей: адресного оператора (&) и оператора косвенного обращения (*). // Программа, показывающая использование указателей #import <Foundation/Foundation.h> int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int count = 10, x; int *intPtr; intPtr = &count; x = *intPtr; NSLog (@"count = %i, x = %i", count, x); [pool drain]; return 0; }
Вывод программы 13.8 count = 10, x = 10
Переменные count и x объявляются обычным образом как целые переменные. В следующей строке переменная intPtr к объявляется ак «указатель на тип int». Эти две строки можно было бы объединить в одну: int count = 10, х, *intPtr;
После этого к переменной count применяется адресный оператор (&), результатом которого является создание указателя на эту переменную, который затем присваивается переменной intPtr.
Выполнение строки х = *intPtr;
происходит следующим образом. Оператор косвенного обращения () сообщает системе Objective-C, что переменная intPtr содержит указатель на другой элемент данных. Этот указатель используется для доступа к нужному элементу данных, тип которого задан при объявлении переменной-указателя. При объявлении переменной мы сообщили компилятору, что переменная intPtr указывает на целые элементы данных, поэтому компилятор «понимает», что значение, указываемое выражением intPtr, является целым. Кроме того, в предыдущей строке мы задали, что intPtr указывает на целую переменную count, поэтому это выражение представляет косвенный доступ к значению count.
В программе 13.9 иллюстрируются некоторые интересные свойства пере-менных-указателей. В ней используется указатель на символ. #import <Foundation/Foundation.h> int main (int arge, char *argv[]) { NSAutoreleasePooi * pool = [[NSAutoreleasePool alloc] init]; char c = “Q"; char *charPtr = &c; NSLog (@"%c %c", c, *charPtr); c = '/'; NSLog (@"%c %c", c, *charPtr); *charPtr = T; NSLog (@“%c %c", c, *charPtr); [pool drain]; return 0; }
} Вывод программы 13.9 QQ // ((
Символьная переменная с определяется и инициализируется со значением 'Q'. В следующей строке этой программы определяется переменная charPtr как «указатель на тип char». Это означает, что любое значение, сохраняемое внутри этой переменной, следует интерпретировать как косвенное обращение (указатель) к символу. Этой переменной можно присвоить начальное значение обычным образом. В этой программе переменной charPtr присваивается указатель на переменную с, и для этого к переменной с применяется адресный оператор &. (Эта инициализация приведет к появлению ошибки компилятора, если определить с после этого оператора, поскольку любая переменная должна быть объявлена раньше ссылки на эту переменную в любом выражении.)
Объявление переменной charPtr и присваивание ее начального значения можно было бы представить в двух отдельных строках char *charPtr; charPtr = &с;
(Но не char *charPtr; *charPtr = &с;
как можно было бы предположить из объявления в одной строке.)
Значение указателя в Objective-C не существует, пока мы не зададим, на какой элемент данных он указывает.
В строке первого вызова NSLog выводится содержимое переменной с и со-держимое этой переменной, указанное с помощью charPtr. Поскольку мы задали, что charPtr указывает на переменную с, выводится и содержимое с, что под-тверждается первой строкой вывода программы.
В следующей строке профаммы символьной переменной с присваивается символ '/\ Поскольку charPtr по-прежнему указывает на с, в следующем вызове NSLog для значения charPtr на терминал выводится новое значение переменной с. Это важно. Если значение charPtr не изменяется, то выражение charPtr всегда означает доступ к значению с. Таким образом, если изменяется значение пере-менной с, то изменяется и значение выражения *charPtr.
Мы говорили, что если значение charPtr не изменено, то выражение *charPtr всегда является ссылкой на значение с. Поэтому в выражении *charPtr = '(';
переменной с присваивается символ «левая круглая скобка». Более формально символ '(' присваивается переменной, на которую указывает charPtr. Мы знаем, что это переменная с, поскольку в начале профаммы мы присвоили charPtr указатель на с.
Эти концепции являются ключом к пониманию действия указателей. Про-думайте их снова, если что-то осталось неясным. Указатели и структуры
Мы определил указатель для базовых типов данных, таких как int или char. Можно определить указатель и на структуру. Выше в этой главе мы определили структуру dale. struct date { int month; int day; int year; };