Разница между указателями на переменные и указателями на структуры в C - PullRequest
6 голосов
/ 20 февраля 2010

Изучая C, я только начал изучать указатели на структуры и у меня есть несколько вопросов.

Предположим, я должен был создать структуру с именем myStructure, а затем создать указатель myStructurePointer, указывающий на myStructure. Являются ли *myStructurePointer и myStructure двумя способами ссылки на одно и то же? Если так, то зачем нужен оператор ->? Кажется, проще использовать *myStructurePointer.variable_name, чем myStructurePointer->variable_name.

Ответы [ 6 ]

8 голосов
/ 20 февраля 2010

Ты прав,

(*structurePointer).field

точно так же, как

structurePointer->field

Что у вас есть, однако:

*structurePointer.field

Который действительно пытается использовать оператор . для переменной указателя, а затем разыменовывать результат этого - он даже не скомпилируется. Вам нужны скобки, как у меня в первом примере выше, если вы хотите, чтобы выражения были эквивалентны. В этом простом случае стрелка сохраняет как минимум пару нажатий клавиш.

Использование -> может иметь больше смысла, если вспомнить случай, когда поле структуры имеет тип указателя, возможно, на другую структуру:

structurePointer->field->field2

против

(*(*structurePointer).field).field2
5 голосов
/ 20 февраля 2010

Проблема с *myStructurePointer.variable_name заключается в том, что * связывается менее плотно, чем ., поэтому это будет интерпретироваться как *(myStructurePointer.variable_name). Эквивалент myStructurePointer->variable_name будет (*myStructurePointer).variable_name, где требуются скобки.

Нет разницы между a->b и (*a).b, но -> проще в использовании, особенно если есть вложенные структуры. (*(*(*a).b).c).d гораздо менее читабелен, чем ´a-> b-> c-> d`.

4 голосов
/ 20 февраля 2010

Чтобы обобщить, изучите приоритет вашего оператора C:

Здесь "." оператор обрабатывается до "*" -> отсюда и необходимость в скобках

1 голос
/ 20 февраля 2010

Деннис Ритчи однажды заметил, что deref, вероятно, должен был быть оператором постфикса 1

Правильно, следующие значения эквивалентны:

pointer->field
(*pointer).field
pointer[0].field

Если бы у оператора косвенности был постфиксный синтаксис C, он выглядел бы несколько иначе, но в этом случае ему бы вообще не понадобилось ->.

Интересно подумать о том, как будут выглядеть обычные C-идиомы в этой альтернативной вселенной ...

do s1++* = c = s2++*;
   while(c);

while(n-- > 0)
    s++* = '\0';

p*.x = 1;
p*.y = 2;
. . .
. . .
. . .

1. См. Развитие языка C. , Деннис М. Ричи

0 голосов
/ 20 февраля 2010

Недавно я изучал C и нашел этот ресурс чрезвычайно полезным.

http://claymore.engineer.gvsu.edu/~steriana/226/C.CheatSheet.pdf

0 голосов
/ 20 февраля 2010

Использование * разыменовывает указатель, поэтому вы можете использовать точечный синтаксис для доступа к полям. Если вы не разыменуете указатель, то вы используете -> для доступа к полям. Вы можете использовать то, что предпочитаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...