int a=17,b=3,r=1;
r = a - a / b * 4 % 3 + r;
in which order a C program will execute this:
- A) / * % + – =
- B) / * % – + =
Can you guys give me a solid explanation of the order in which a C program will execute these?
kl-kl+jkljkl-jk-l-jkl-jk-l-jkl
8
The expression will be parsed as
(a - (((a / b) * 4) % 3)) + r;
Graphically:
+
/
- r
/
a %
/
* 3
/
'/' 4
/
a b
/
, *
, and %
all have higher precedence than +
and -
, and arithmetic operators are left-associative (which is why it doesn’t parse as a / (b * (4 % 3))
).
But…
Precedence does not control order of evaluation. Each of the subexpressions a
, b
, and r
may be evaluated in any order, even simultaneously. The subexpression a - a / b * 4 % 3
may be evaluated either before or after r
. The compiler is free to order evaluations differently from what you would expect, as long as the result obeys the precedence and associativity rules above.
The result is dictated by precedence and associativity.
Multiplication has higher precedence than addition, so
a + b * c
is equivalent toa + ( b * c )
.d * e + f
is equivalent to( d * e ) + f
.
Addition and subtraction have the same precedence, so we consult associativity. They are left-associative, so
a + b - c
is equivalent to( a + b ) - c
.d - e + f
is equivalent to( d - e ) + f
.
The multiplication, division and modulus operators also have the same precedence, and are left-associative.
A combined example:
a + b * c + d
is equivalent to( a + ( b * c ) ) + d
.
Precedence and associativity help define what the code means (how it’s parsed), but you asked about evaluation order. That can’t be answered because C doesn’t dictate the order in which operands are evaluated in these circumstances. For example,
a * b + c / d
is equivalent to( a * b ) + ( c / d )
From that, the following is obviously mandated:
- Both
a
andb
need to be evaluated before the*
. - Both
c
andd
need to be evaluated before the/
. - Both
*
and/
need to be evaluated before the+
.
But that still leaves many ways of computing the result.
a
,b
,*
,c
,d
,/
,+
b
,a
,*
,d
,c
,/
,+
c
,d
,/
,a
,b
,*
,+
a
,b
,c
,d
,*
,/
,+
d
,c
,b
,a
,*
,/
,+
d
,c
,b
,a
,/
,*
,+
- etc.
C doesn’t define which one of these the compiler must use. It’s free to use any order which achieves the desired result. It can even change which operations are performed (a simple example of which is changing a division into a multiplication by the inverse), as long as it obtains the correct result.