Программирование на Objective-C 2.0
Шрифт:
рх указывает на п следующих элементов в массиве, независимо от их типа данных.
Предположим, что fractsPtr указывает на дробь (fraction), содержащуюся в массиве дробей. Ее нужно сложить с дробью, содержащейся в следующем элс- менте этого массива, и прис воить результат объекту result класса Fraction. Для этого можно написать: result = [*fractsPtr add: *(fractsPtr +1)];
Операторы приращения (++) и уменьшения (—) особенно удобны при работе с указателями. Применение к указателю оператора (++) дает такой же результат, как прибавление к указателю 1, а оператор уменьшения (—) действует также, как вычитание 1 из указателя. Таким образом, если textPtr определен как указатель на тип char и указывает
textPtr будет указывать на следующий си мвол в массиве text, то есть на text[1 ]. Аналогичным образом, в результате оператора --textPtr;
textPtr будет указывать на предыдущий символ в массиве text (если, конечно, textPtr не указывал на начало массива text перед выполнением этого оператора).
В Objective-C вполне допустимо сравнение двух переменных-указателей. Это особенно полезно при сравнении двух указателей на элементы одного массива. Так можно убедиться, что указатель valuesPtr не указывает дальше конца массива, содержащего 100 элементов. Для этого нужно сравнить этот указатель с ука-зателем на последний элемент массива. Например, выражение valuesPtr > &values[99]
будет иметь значение TRUE (ненулевое значение), если valuesPtr указывает даль-ше последнего элемента массива values, и будет иметь значение FALSE (нулевое значение) в противном случае. В соответствии с предыдущим описанием мы можем заменить это выражение на его эквивалент valuesPtr > values + 99
values без индекса — это указатель на начало массива values. (Эквивалентно &values[0].)
В программе 13.12 показано использование указателей на массивы. Функция arraySum вычисляет сумму целых элементов, содержащихся в массиве. // Функция для вычисления суммы элементов, содержащихся в массиве целого типа #import <Foundation/Foundation.h> int arraySum (int array[], int n) { int sum = 0, *ptr; int *arrayEnd = array + n; for ( ptr = array; ptr < array End; ++ptr) sum += *ptr; return (sum); } int main (int argc, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int arraySum (int array[], int n); int values[10] = { 3, 7, -9, 3,6, -1, 7, 9, 1, -5 }; NSLog (@"The sum is %i", arraySum(values, 10)); [pool drain]; return 0; }
Вывод программы 13.12 The sum is 21 (Сумма равна 21)
Внутри функции arraySum определен указатель arrayEnd на тип int, который указывает «ячейку» непосредственно вслед за последним элементом массива. За-тем для последовательного перебора элементов массива используется цикл for. При входе в цикл ptr указывает на начало массива. На каждом шаге цикла к сумме прибавляется элемент массива, на который указывает ptr. Затем в цикле for значение ptr наращивается, чтобы указывать на следующий элемент массива. Когда ptr указывает «ячейку» после конца массива, происходит выход из цикла for, и значение sum возвращается вызывающей процедуре. Это массив или это указатель?
Чтобы передать массив функции, нужно просто передать имя этого массива, как при вызове функции arraySum. Но мы говорили, что для создания указателя на массив достаточно задать имя этого массива. Из этого следует, что при вызове функции arraySum функции передается указатель на массив values. Именно это и происходит, поэтому мы можем изменять элементы массива внутри функции.
Но если функции перелается указатель на массив, то почему формальный параметр внутри функции не объявлен как указатель? Иначе говоря, почему при объявлении array в функции arraySum не используется следующее объявление: int *array;
Не следует ли все обращения к массиву вну три функции выполнять с помо-щью переменных-указателей?
Чтобы ответить на эти вопросы, мы должны сначала вернуться к тому, что уже
Как видите, указатели и массивы тесно связаны друг с другом, и поэтому внутри функции arraySum можно объявить массив как «массив целых значений (типа int)» или как «указатель на тип int».
Если использовать индексы для доступа к элементам массива, то соответ-ствующий формальный параметр нужно объявить как массив. Если использовать аргумент как указатель на массив, то его нужно объявить как указатель. Указатели на символьные строки
Чаще всего указатель на массив используется как указатель на символьную стро-ку. Чтобы показать, насколько просты в работе указатели на символьные строки, напишем функцию с именем copyString для копирования одной строки в другую. Используя обычные методы написания такой функции с помощью индексирования массивов, можно составить следующий код: void copyString (char to[], char from[]) { int i; for (i = 0; fromp] != '\0'; ++i) to[i] = from[i]; to[i] = '\0'; }
Выход из цикла for происходит в тот момент, когда обнаруживается нуль- символ, что и делает последний оператор в этой функции.
Если написать функцию copyString с использованием указателей, то индексная переменная i не нужна. Версия с указателями показана в программе 13.13. #import < Foundation/Foundation.h> void copyString (char *to, char *from) { for (; *from != '\0'; ++from, ++to ) *to = *from; *to = '\0'; } int main (int arge, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; void copyString (char *to, char *from); char string [] = "Копируемая строка"2; char string2[50]; copyString (string2, string 1); NSLog(@"%s", string2); copyString (string2, "Строка-константа"); NSLog(@"%s", string2); [pool drain]; return 0; }
Вывод программы 13.13 Копируемая строка Строка-константа
В функции copyString определены два формальных параметра (to и from) как указатели на символы, а не на массивы символов, как в предыдущей версии copyString. Это показывает, каким образом эти две переменные будут использо-ваться в функции.
Затем происходит вход в цикл for (без начальных условий) для копирования строки, которую указывает параметр from (откуда) в строку, которую указывает параметр to (куда). На каждом шаге цикла выполняется увеличение указателей from и to на I. В результате указатель from указывает на следующий символ для копирования из исходной строки, и указатель to указывает место, в котором будет сохранен этот символ. Когда указатель from указывает на нуль-символ, происходит выход из цикла for. Затем функция помещает нуль-символ в конец скопированной строки.
В процедуре main функция copyString вызывается дважды. В первый раз в строку string2 копируется содержимое строки stringl, во второй раз в строку string2 копируется содержимое константной символьной строки. Константные символьные строки и указатели
Из copyString (string2, "Строка-константа");
следует, что если константная символьная строка передается как аргумент фун-кции, эта символьная строка фактически передается указателю. Это верно не только в данном случае. Обобщая, можно сказать, что если константная сим-вольная строка используется в Objective-C, то на эту символьную строку создается указатель.