ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C Часть 1

Указатели

Перед тем как рассказать вам о более сложных типа данных хочу вас посветить в некоторые сложные понятия, представляющие основу языка C. Эти понятия могут отпугнуть начинающих программистов. Но не бойтесь, если вы не поймёте всё сразу! Понимание принципа работы указателей очень полезно, но к счастью не сильно важно на начальном этапе изучения Objectice-C.

Когда мы создаем переменную устройство (iPhone/iPad) соединит эту переменную с областью в памяти, для хранения ее значения. Например:

<code data-result="[object Object]">int x = 4;</code>

При запуске, устройство найдет немного незанятого места в памяти и отметит, что в этом месте теперь записана переменная x. В первую очередь мы указываем тип переменной (в данном случае int) говорит компьютеру сколько памяти требуется для хранения переменной x. Если мы укажем тип переменной long или double, нужно будет выделить больше места.

Инструкция присвоения x = 4 присваивает значение 4 в зарезервированной памяти. Конечно, компьютер запоминает где в памяти было сохранено значение переменой х. Другими словами запоминая адрес переменной х. Поэтому, каждый раз, когда мы используем х в нашей программе, телефон «смотрит» в нужном месте (по правильному адресу) и может найти актуальное значение переменной х.

Указатель — это просто переменная, хранящая адрес другой переменной в памяти.

Следующий код выводит в консоль адрес переменной в памяти.

<code data-result="[object Object]">NSLog(@"%d", &amp;x);</code>

Как вы уже заметили, адрес мы получаем с помощью добавления символа & перед переменной.

Когда устройство вычисляет выражение x он возвращает значение переменной x (в нашем примере он вернет 4). В противоположность этому, когда устройство вычисляет выражение &x, он возвращает адрес переменной x, но не её значение. Адрес это номер который обозначает определённое место в памяти компьютера (что-то типа того как номер комнаты обозначает вполне определённую комнату в отеле).

Давайте рассмотрим примеры использования указателей. В следующем коде мы объявляем указатель.

<code data-result="[object Object]">int *y;</code>

Эта команда определяет переменную y, которая содержит адрес переменной целочисленного типа (на данный момент она не содержит адрес переменной, т.к. не произведена инициализация ). Повторяю: она не содержит переменную типа int, но она содержит адрес в памяти, где лежит эта переменная. Для того чтобы присвоить переменной y адрес переменной x вам нужно написать следующий код:

<code data-result="[object Object]">y = &amp;x;</code>

Теперь переменная y указывает на адрес переменной x. Используя переменную y вы можете отыскать переменную x. Как это сделать?

Вы можете узнать значение на которое указывает переменная y путем добавления звездочки перед указателем. Например, выражение*y возвратит значение 4. Оно дает такой же результат, как если бы обратились непосредственное к переменной x. Команда *y = 5; равносильна выполнению x = 5;.

Использование указателей удобно, потому что вы можете захотеть обращаться не к значению переменной, а к ее адресу. Например, вы можете захотеть создать функцию, которая увеличивает значение переменной на 1. Что ж, можно это сделать вот так:

<code data-result="[object Object]">- (void)increment:(int)x {
    x = x + 1;
}</code>

Но у вас ничего не получится. Если вызвать эту функцию из программы, вы не получите тот результат, который ожидаете.

<code data-result="[object Object]">int myValue = 6; 
increment(myValue); 
NSLog(@"%d: ", myValue);</code>

Результатом выполнения этого кода будет 6. Почему? Разве вы не увеличили значение переменной myValue вызвав функцию инкремента? Нет. Смотрите, функция берет только значение переменной myValue, увеличивает его на единицу и… прекращает выполнение. Функция работает только со значением переменной, которую вы указали в качестве аргумента, а не с переменной, которая хранит это значение. Даже если вы изменили значение x, вы изменили только значение переменной, которое получила функция.

Любое такое изменение будет потеряно, когда будет осуществлен возврат из функции. Кроме того x даже не обязательно присваивать переменную. Если вы напишите increment(5); какой результат получите?

Если вы хотите написать функцию инкремента, которая действительно работает, то есть принимает в качестве аргумента переменную и изменяет значение этой переменной вам нужно передать в функцию адрес этой переменной. Итак, используйте указатель как аргумент:

<code data-result="[object Object]">- (void)increment:(int*)x {
    *x = *x + 1;
}</code>

Затем вы можете вызвать эту функцию:

<code data-result="[object Object]">int myValue = 6; 
[self increment:&amp;myValue];
NSLog(@"%d: ", myValue);</code>

Теперь myValue равно 7.

Но это лишь пример, использования указателей. В нашем конкретном случае, основываясь на уже имеющихся знаниях функцию мы напишем вот так:

<code data-result="[object Object]">- (int)increment:(int)x {
    x = x + 1;
    return x;
}</code>

А вызывать ее будем так:

<code data-result="[object Object]">int myValue = 6; 
myValue = [self increment:myValue];
NSLog(@"%d: ", myValue);</code>

То есть, возвращаясь в начало статьи я повторюсь, что понимание принципа работы указателей не сильно важно на начальном этапе изучения Objectice-C. Но эта статья поможет вам понять принцип работы переменных более сложных типов, о которых пойдет речь дальше.

Comments are closed.