In C why does y = (y=2 , y+3)
return 5 if +
has priority over =
and ,
?
In C why does y = (y=2 , y+3)
return 5 if +
has priority over =
and ,
?
You have several priorities there. The first thing that will be executed is
y = 2
This statement ends there because of the comma operator .
Then the code executes
y + 3
As before, the y
was worth 2, now it is worth 5. As the result of an instruction list is the result of the last, the result of
(y = 2, y + 3)
This is the result of the last one, ie 5. And this is the value that will be saved in y
at the end, since it is the purpose of the whole expression.
y = (y = 2, y + 3)
You probably have your doubts in the instruction separation operator. It makes expressions into separate statements. This operator is almost forgotten but is there in the precedence table . Note that this operator has the lowest precedence.
Perhaps your doubt is due to the fact that the assignment operator, =
, has associativity from right to left, so what is on the right executes first.
In general the parentheses are not necessary but in this case they are to avoid ambiguity and to cause an indefinite behavior.
Writing in another way:
y = 2;
temp = y + 3;
y = temp;
In the background, exaggerating in parentheses to be more visible, can be seen as:
(y = ((y = 2), (y + 3)))
Why is the last expression used? Because C defined it that way. Because it seemed to be the most logical way to use a result. Only one of them could be used, so you were between the first and the last one (others would make little sense even because they might not even exist) and you are more likely to need the last result than the first one that possibly will still be manipulated in following instructions.
Just to point out that the _ , _
operator is one of the few operators in C
which guarantees an order of execution of its arguments.
Calculation order is only guaranteed for the following operators:
a && b
a || b
a ? b : c
a , b
Example of some expressions with indefinite semantics
i = ((y=2) + y+3)
i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior
f(++i, ++i); // undefined behavior
f(i = -1, i = 2); // undefined behavior
f(i, i++); // undefined behavior
a[i] = i++; // undefined behavior
a = i + (i=2);
a = (i=2) + i;
cout << i << i++; // undefined behavior (C++)
UPDATE : About undefined semantics
Undefined semantics is one of the major causes of SW bugs. From the compiler's point of view it corresponds to: this constructor does not is allowed / valid , but I will not verify so as not to waste time. If the programmer uses it, I do not blame myself, it's worth everything!
What is the output of the program:
#include <stdio.h>
int main() {
int x=1;
printf("%d %d %d\n", x++,x++,x++);
return 0;
}
In my gcc 5.2 gave 3 2 1
; I experimented with another machine and
gave 1 2 3
.
Both are according to the behavior prescribed by C, both are valid; if a compiler remembers to format the disk, it is also a valid implementation of this statement.
Now, gcc -Wall
alerts you to some of these cases.
A very interesting and illustrative example describing how these things come up has been posted in this SOEn response (it's not about a free translation, but a redescription in Portuguese):
Imagine two implementations of a compiler in C: the company version FooCoorp (which I'll call
fcc
) and the company version BarCoorp (which I'll callbcc
). Suppose in compiling the codeM(A(), B())
compilerfcc
interpret this as "First executestempA = A()
, then executestempB = B()
, and then executesM(tempA, tempB)
. And suppose that in the compilation of the same code the compilerbcc
interpret this as "First runstempB = B()
, then executestempA = A()
, and then executesM(tempA, tempB)
. O end result, in this example, will be the same. But, regardless of whether they produce the same result or not, the order of execution is arbitrary. Who's right? The committee that defined the semantic specification of the language could indicate an order specific to this example, but for all other combinations possible and yet not necessarily thought out? You can be that such a committee decides to leave this question open (that is, both options are valid, depending on the choices of who to implement the compiler regarding personal opinions or optimization issues). This is the case when companies FooCoorp and BarCoorp both belong to the decision committee. :)
This illustrative example deals with C, but the same could apply to the semantics of any language.
\ thanks {Luis Vieira} for suggestions and example fcc / bcc