2015-04-05 4 views
0

Я изучаю указатели в Obj-C. Рассмотрим следующий код:Разница указателей

char c = 'Q'; 
char *charPtr; 
charPtr = &c; 

Во второй строке мы создаем переменную указатель типа полукокса и назовите его charPtr. По моему мнению, это всего лишь указатель на адрес памяти, который содержит некоторое значение типа char.

В третьей строке мы присваиваем значение charPtr (адрес памяти) другому адресу памяти, который содержит значение c.

Мой вопрос в том, в чем разница между charPtr и * charPtr?

Когда я писал *charPtr = &c есть "желтый" предупреждение - Incompatible pointer to integer conversion assigning to 'char' from 'char *'; remove &

App аварии, если запущен (exc_bad_access)

Когда я писал **charPtr = &c; компилятор предупредит меня с ошибкой: Indirection requires pointer operand ('int' invalid)

Резюме, я хотите знать разницу между charPtr и *charPtr, и что такое **charPtr (2 звездочки).

+1

'charPtr' - указатель типа' char * '. '* charPtr' имеет тип' char'; это объект 'char', на который указывает указатель. '** charPtr' является незаконным, потому что' * charPtr' не является указателем. –

+0

@ KeithThompson в этом случае имеет право использовать 2 звездочки и что это значит? Благодарим вас за разъяснения. –

+2

@Evgeniy Kleban Представьте, что у вас есть абстрактная декларация указателя T * ptr; T может быть любым типом, который является ptr, может быть указателем на объект типа T, где T - любой тип. Если T в свою очередь является типом указателя, например, char *, тогда вы получите char * * ptr. Теперь, если вы хотите объявить указатель на объект ptr, который имеет тип char **, вы должны заменить в выражении T * ptr T на char **, и вы получите char *** ptr; –

ответ

3

charPtr - это переменная, которая содержит указатель на значение типа char. После строки 2 он содержит адрес переменной c.

*charPtr - это выражение, которое разыскивает указатель и обращается к значению по указанному адресу. Поскольку charPtr указывает на значение типа char, выражение *charPtr имеет тип char. Если вы прочитали из него, например char foo = *charPtr;, вы получите char в указанном месте. В этом случае вы получаете значение c, которое равно 'Q'. Если вы напишете ему, например *charPtr = 'A';, вы сохраните новое значение в указанном месте. В этом случае вы меняете содержимое c.

**charPtr является синтаксической ошибкой, поскольку charPtr не является указателем на указатель. Выражение имеет форму двойного разыменования: первое разыменование - *charPtr, как и выше. Применяя к нему оператор *, он снова пытается разыменовать его, но тип *charPtr - char. Это не указатель, поэтому он не может быть разыменован.

Вы могли бы иметь переменную так:

char **charPtrPtr = &charPtr; 

Теперь charPtrPtr является переменная, которая содержит адрес переменной charPtr. Его тип: char**.

*charPtrPtr разыгрывает указатель, который он удерживает, и получает значение, на которое он указывал. Это значение charPtr, которое, в свою очередь, является указателем на c.

**charPtrPtr является двойным разыменованием. Это приложение унарного оператора * к *charPtrPtr.Так как *charPtrPtr фактически совпадает с charPtr, **charPtrPtr фактически совпадает с *charPtr, что совпадает с c.

+0

определенно лучший ответ, спасибо, Кен, теперь все это ясно для меня! –

1
  • char *charPtr; - вы объявить переменную с именем charPtr типа char *, то есть «указатель на символ»
  • charPtr = &c; - вы присвоив переменной charPtr адреса переменной с
  • *charPtr - в этом случае символ '*' является оператором косвенности, который означает получение значения в адресе, указанном charPtr. Тип * charPtr в этом случае будет charНЕchar*)

Теперь за указанные в заявлении *charPtr = &c вы пытаетесь присвоить адрес переменного с (&c) к полукоксу (*charPtr), поэтому вы получаете предупреждение Incompatible pointer to integer conversion assigning to 'char' from 'char *'; remove &.

При запуске приложения вы будете пытаться назначить адрес (размером 4 или 8 байт) переменной типа char (обычно 1 или 2 байта), поэтому ваше приложение будет аварийно завершено на exc_bad_access

+0

Спасибо Amnon за ваш ответ! Особенно для объяснения ошибок. –

3

Проще говоря, *charPtr ссылается на значение, на которое указывает charPtr. Однако, поскольку ответы StackOverflow должны быть немного длиннее одного предложения, я попытаюсь дать вам аналогию.

Как вы знаете, указатель вроде дорожного знака, говоря: «вещь, которую вы ищете, есть в A/B/C независимо». Указатель можно использовать несколькими способами.

Прежде всего, вы можете указать знак в другое место, что эквивалентно charPtr = &c, говоря «вместо A/B/C, теперь используйте c как пункт назначения».

Во-вторых, вы также можете использовать указатель, чтобы изменить то, на что оно указывает, что эквивалентно *charPtr = 'Q', что на самом деле не изменяет сам указатель, но изменяет содержимое поля, на которое оно указывает. Сохраняя аналогию с дорожным знаком, как будто знак способен изменить название города (то есть содержание var c)

Наконец, сами указатели также могут указывать на значок, похожий на знак указывая на следующий знак. Например, char **cc = &charPtr будет знаком, указывающим на оригинальный знак, и в этом случае **cc может использоваться для доступа к фактическому значению, а *cc - это содержимое первого знака (адрес фактического значения). Это можно расширить, насколько может видеть глаз, или, по крайней мере, насколько это практически желательно.

+0

Спасибо Анри, очень хороший ответ и аналогия дорожных знаков! –

Смежные вопросы