* p ++ -> str: Понимание оценки -> - PullRequest
7 голосов
/ 30 июня 2019

Мой вопрос касается следующей строки кода, взятой из "Языка программирования C", 2-е издание:

*p++->str;

Книга говорит, что эта строка кода увеличивает p после доступа к тому, на что указывает str.

Мое понимание таково:

  • Приоритет и ассоциативность говорят, что порядок, в котором будут оцениваться операторы, равен

    1. ->
    2. ++
    3. *
  • Оператор приращения постфикса ++ возвращает значение (то есть значение его операнда) и имеет побочный эффект увеличения этого операнда до следующей точки последовательности (т. Е. Следующего;)

  • Приоритет и ассоциативность описывают порядок, в котором оцениваются операторы, а не порядок, в котором оцениваются операнды операторов.

Мой вопрос:

Мой вопрос касается оценки оператора наивысшего приоритета (->) в этом выражении. Я считаю, что оценивать этот оператор - значит оценивать оба операнда, а затем применять оператор.

С точки зрения оператора -> левый операнд p или p ++? Я понимаю, что оба возвращают одно и то же значение.

Однако, если первый вариант верен, я хотел бы спросить: «Как при оценке оператора -> можно игнорировать присутствие ++».

Если второй вариант верен, я бы спросил: "не вычисляет ли -> в этом случае, тогда требует оценки оператора с более низким приоритетом ++ здесь (и оценка ++ завершается до оценки -> ) "?

Ответы [ 2 ]

6 голосов
/ 30 июня 2019

Постфикс ++ и -> имеют одинаковый приоритет. a++->b анализируется как (a++)->b, т. Е. ++ выполняется первым.

*p++->str; выполняется следующим образом:

  • Выражение разбирается как *((p++)->str). -> - это оператор мета-постфикса, т.е. ->foo - это оператор постфикса для всех идентификаторов foo. Постфиксные операторы имеют наивысший приоритет, за ними следуют префиксные операторы (например, *). Ассоциативность на самом деле не применяется: существует только один операнд и только один способ «связать» его с данным оператором.

  • p++ оценивается. Это дает (старое) значение p и планирует обновление, устанавливая p в p+1, что произойдет в некоторый момент перед следующей точкой последовательности. Назовите результат этого выражения tmp0.

  • tmp0->str оценивается. Это эквивалентно (*tmp0).str: оно разыменовывает tmp0, который должен быть указателем на структуру или объединение, и получает член str. Назовите результат этого выражения tmp1.

  • *tmp1 оценивается. Это разыменовывает tmp1, который должен быть указателем (на полный тип). Назовите результат этого выражения tmp2.

  • tmp2 игнорируется (выражение находится в пустом контексте). Мы достигаем ; и p должны быть увеличены до этой точки.

6 голосов
/ 30 июня 2019

Чтобы понять выражение *p++->str, вам нужно понять, как работает *p++ или вообще, как увеличение постфикса работает с указателями.

В случае *p++ значение в местоположении, на которое указывает p, разыменовывается до увеличения указателя p.
n1570 - §6.5.2.4 / 2:

Результатом оператора postfix ++ является значение операнда. Как побочный эффект, значение объекта операнда увеличивается (то есть к нему добавляется значение 1 соответствующего типа). [...]. Вычисление значения результата выполняется до появления побочного эффекта обновления сохраненного значения операнда .

В случае *p++->str, ++ и -> имеют равный приоритет и оператор выше *. Это выражение будет заключено в скобки как *((p++)->str) согласно правилу приоритета оператора и ассоциативности.

Здесь важно отметить приоритет и ассоциативность не имеет ничего общего с порядком оценки . Таким образом, хотя ++ имеет более высокий приоритет, не гарантируется, что p++ будет оцениваться первым. Это означает, что выражение p++ (в выражении *p++->str) будет оцениваться согласно правилу, приведенному выше из стандарта. (p++)->str получит доступ к str члену p, указывает на него, а затем его значение разыменовывается, а затем значение p увеличивается в любое время между последней и следующей точкой последовательности.

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