Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator precedence and order of evaluation for complex expression

Tags:

I was looking at the following code:

#include <stdint.h>

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

  *pVal = i *= 10;
}

At the first glance it is clear that before returning from foo(), *pVal would be 80 as well as the value of i. And this is indeed what happens according to 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

However after checking the operator precedence from here, the precedence of = is higher than the precedence of *=, so it seems that the value of *pVal should be 8 and the value of i should be 80...

What am I missing here?

EDIT:

In addition to the great answer by melpomene, there is also a nice Wikipedia page.

like image 852
Alex Lop. Avatar asked Jan 09 '19 10:01

Alex Lop.


1 Answers

The table you linked to shows all assignment operators (including = and *=) at the same precedence level: 14.

They're also right associative, so x = y *= z parses as x = (y *= z), as expected.


If = had a higher precedence than *=, then x = y *= z would parse as (x = y) *= z, which would be a hard error because = doesn't yield an lvalue (you cannot assign to the result of an assignment). If = did return its left operand as an lvalue, then (x = y) *= z would have undefined behavior because it's modifying x twice without an intervening sequence point. And if there were a sequence point after the inner assignment, the final values of the variables after (*pVal = i) *= 10 would be i = 8 (unmodified) and *pVal = 80.

Live demo (using Perl, which has a = that returns an lvalue as described above)

like image 144
melpomene Avatar answered Nov 12 '22 18:11

melpomene