Приоритет оператора и порядок вычисления для сложного выражения - PullRequest
0 голосов
/ 09 января 2019

Я искал следующий код:

#include <stdint.h>

void foo(uint32_t *pVal)
{
  uint32_t i = 8;

  *pVal = i *= 10;
}

На первый взгляд ясно, что перед возвратом из foo() значение *pVal будет равно 80, а также значение i. И это действительно то, что происходит согласно godbolt.org :

foo:                                    # @foo
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     dword ptr [rbp - 12], 8
        imul    eax, dword ptr [rbp - 12], 10
        mov     dword ptr [rbp - 12], eax
        mov     rdi, qword ptr [rbp - 8]
        mov     dword ptr [rdi], eax
        pop     rbp
        ret

Однако после проверки приоритета оператора из здесь , приоритет = выше, чем приоритет *=, поэтому кажется, что значение *pVal должно быть 8, а значение i должно быть 80 ...

Что мне здесь не хватает?

EDIT

В дополнение к великолепному ответу melpomene , есть также хорошая страница Википедии .

1 Ответ

0 голосов
/ 09 января 2019

В таблице, к которой вы привязаны, показаны все операторы присваивания (включая = и *=) с одинаковым уровнем приоритета: 14.

Они также правы, поэтому x = y *= z анализируется как x = (y *= z), как и ожидалось.


Если = имеет более высокий приоритет, чем *=, тогда x = y *= z будет анализироваться как (x = y) *= z, что будет серьезной ошибкой, поскольку = не дает lvalue (вы не можете присвоить результату назначения). Если бы = вернул свой левый операнд как lvalue, то (x = y) *= z имел бы неопределенное поведение, потому что он дважды изменял x без промежуточной точки последовательности. И если бы после внутреннего присваивания была точка последовательности, конечные значения переменных после (*pVal = i) *= 10 были бы i = 8 (без изменений) и *pVal = 80.

Демонстрационная версия (с использованием Perl, у которого = возвращает значение l, как описано выше)

...