Чтение онлайн

на главную

Жанры

Программирование на Objective-C 2.0
Шрифт:

рх указывает на п следующих элементов в массиве, независимо от их типа данных.

Предположим, что fractsPtr указывает на дробь (fraction), содержащуюся в массиве дробей. Ее нужно сложить с дробью, содержащейся в следующем элс- менте этого массива, и прис воить результат объекту result класса Fraction. Для этого можно написать: result = [*fractsPtr add: *(fractsPtr +1)];

Операторы приращения (++) и уменьшения (—) особенно удобны при работе с указателями. Применение к указателю оператора (++) дает такой же результат, как прибавление к указателю 1, а оператор уменьшения (—) действует также, как вычитание 1 из указателя. Таким образом, если textPtr определен как указатель на тип char и указывает

на начало массива элементов типа char с именем text, то в результате оператора ++textPtr;

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;

Не следует ли все обращения к массиву вну три функции выполнять с помо-щью переменных-указателей?

Чтобы ответить на эти вопросы, мы должны сначала вернуться к тому, что уже

говорили об указателях и массивах. Если valuesPtr указывает на тип элемента, содержащегося в массиве с именем values, то выражение (valuesPtr + i) эквива-лентно выражению valuesfi] в предположении, что valuesPtr сначала указывал на начало массива values. Из этого следует, что мы можем использовать выражение (values + i) для обращения к i-му элементу массива values. В общем случае, если х — массив любого типа, то выражение x[i] всегда можно записать в эквивалентной форме *{х + i).

Как видите, указатели и массивы тесно связаны друг с другом, и поэтому внутри функции 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, то на эту символьную строку создается указатель.

Поделиться:
Популярные книги

Газлайтер. Том 21

Володин Григорий Григорьевич
21. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Газлайтер. Том 21

На границе империй. Том 6

INDIGO
6. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.31
рейтинг книги
На границе империй. Том 6

Гримуар темного лорда VI

Грехов Тимофей
6. Гримуар темного лорда
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Гримуар темного лорда VI

Воин-Врач

Дмитриев Олег
1. Воин-Врач
Фантастика:
попаданцы
альтернативная история
историческое фэнтези
6.00
рейтинг книги
Воин-Врач

Страж Кодекса

Романов Илья Николаевич
1. КО: Страж Кодекса
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Страж Кодекса

Мечник Вернувшийся 1000 лет спустя

Ткачев Андрей Юрьевич
1. Вернувшийся мечник
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Мечник Вернувшийся 1000 лет спустя

Я – Легенда

Гарцевич Евгений Александрович
1. Я - Легенда!
Фантастика:
боевая фантастика
попаданцы
рпг
фантастика: прочее
5.00
рейтинг книги
Я – Легенда

"Дальние горизонты. Дух". Компиляция. Книги 1-25

Усманов Хайдарали
Собрание сочинений
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Дальние горизонты. Дух. Компиляция. Книги 1-25

Вперед в прошлое 2

Ратманов Денис
2. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 2

Князь Целитель 2

Ткачев Андрей Юрьевич
2. Князь Целитель
Фантастика:
боевая фантастика
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Князь Целитель 2

Последний реанорец. Том VIII

Павлов Вел
7. Высшая Речь
Фантастика:
фэнтези
попаданцы
аниме
5.75
рейтинг книги
Последний реанорец. Том VIII

На границе империй. Том 10. Часть 2

INDIGO
Вселенная EVE Online
Фантастика:
космическая фантастика
5.00
рейтинг книги
На границе империй. Том 10. Часть 2

Я граф. Книга XII

Дрейк Сириус
12. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я граф. Книга XII

Князь Андер Арес 3

Грехов Тимофей
3. Андер Арес
Фантастика:
рпг
аниме
фэнтези
5.00
рейтинг книги
Князь Андер Арес 3