[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [avr-gcc-list] Question about gcc preprocessing and port/pinassignme
From: |
Dave Hansen |
Subject: |
RE: [avr-gcc-list] Question about gcc preprocessing and port/pinassignments |
Date: |
Fri, 10 Dec 2004 18:32:34 -0500 |
From: "wbounce" <address@hidden>
[...]
I do not know the inner working of gcc but I disagree with your
statement
"The only thing that the language promises is that all side effects from
the expression are completed before the next statement is executed."
In your example
a = (b = 3) + 4;
Order of operation requires the following
Assign 3 to b (because of the ())
Return 3 from that
Add 4
Then assign result (7) to a
It is required to do those things, but it is not required to do them in
exactly that order. The compiler is free to generate code as if you had
written
a = 7;
b = 3;
instead. The volatile keyword prevents certain optimizations across
sequence points, but there's only one sequence point in the original example
(the end of the full expression, sometimes mis-characterized as the
semicolon). The inner parentheses constrain the associativity of the
operators, but not the order of their execution. In particular, parentheses
do not introduce a sequence point.
C DOES have order of operation and operations on the same level are
supposed to be processed left to right.
In at least one sense you are correct. Given an expression like
a + b + c + d
the implementation is required to return the value
(((a + b) + c) + d)
It may only reorder the calculation if the result of the new ordering is
identical to that required. IOW, it must behave as-if it had performed the
caluclation in the implied order.
I have previously made the argument that, if b is volatile,
a = b = c;
the implementation must first write the result (c) to b, then read b and
write that to a. I based this on the wording of 6.5.16p3, which says (in
part): "An assignment expression has the value of the left operand after the
assignment." Since the left operand (b) is volatile, and the value of a
volatile may change for reasons not visible to the compiler, I reasoned that
the value to be written to a cannot be known until b is read, and b cannot
be read until after it is written.
I was told unequivocally that I was wrong by several authors of the
standard. I can still argue that while it might not be what they _meant_,
it is what the words _say_. But it is not a fight worth fighting: No code
which relied on storage order this way would get through one of _my_ code
reviews. Even if I'm right, others disagree, the chances an implementation
disagrees with me is pretty strong, and it's pretty simple to break the
expression into two statements to get the desired result:
b = c;
a = b;
Finally, note that if a and b are _not_ volatile, there's not even any
guarantee that the two statements above will write the value to b before it
is written to a. If a and b are not volatile, the compiler (by the as-if
rule) can optimize code across sequence points and so can generate code
equivalent to
a = c;
b = a;
or
a = c;
b = c;
or
_temp = c;
a = _temp;
b = _temp;
or any of infinitely many others. The only requirement is that the result
of the statements is the same as it would be if the statements had been
executed exactly as written.
HTH,
-=Dave