avr-gcc-list
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]