A question for every C programmer out there. What does the following C program [with a few post-increment(++) and bitwise OR(|) operators thrown in to confuse you] output ?
I thought iIndex will be 5 and iValue will be 0x01020304. After compiling in Visual Studio 2005, the program output iIndex as 5 but iValue as 0x01010101. Confounded, I compiled with Visual Studio 2008 to check whether there was any difference. Nope nothing changed. So what is going on here ?
Operator precedence wise post increment operator (++) is evaluated before left shift operator (<<) so why would the increments happen after the bitwise OR even though ORing is outside parantheses ?
I searched around in ISO C standard document but could not find anything that would explain the behavior. (In a 550 page document, one can never be sure of finding the legalese that would apply to a specific case.)
I thought I could at least see what Microsoft compiler was doing if I changed the pre increments to post increments. (++iIndex instead of iIndex++). And sure enough iValue changed to 0x05050505. After playing around with various combinations of ++ and --, it was clear that pre increment/decrement operators were evaluated first to update iIndex. Then the bitwise shifts and ORs were performed on that value of iIndex to result in iValue. This is followed by updating iIndex with post increment/decrement operators specified.
Try working the output of the following -
Since I do not have a linux installation handy to try things out I have no idea how gcc evaluates these. Until I find the relevant part of the C standard (or lack thereof), this will be a rather disturbing hole in my understanding of C expressions...
Update [May 26 2008] I found following two possibly related paragraphs in C spec -
a) From section 6.5 on Expressions subsection 2
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored. (71)...
71)This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
i = i + 1;
a[i] = i;
b) From section 6.5.14 Logical OR operator subsection 3
Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is a sequence point after the evaluation of the first operand. If...
The first paragraph clearly renders the expression in question undefined. The first paragraph may also explain why at most one increment happened during evaluation of above expression with the rest of the increments happening afterwards. I say may because the C specification does not define sequence points clearly enough for me to be absolutely sure.
The second paragraph makes the expression even more problematic to evaluate. If left to right evaluation is not guaranteed, which is something I was not aware of, and each of the sub-expressions (between |s) has side effect on the others (because iIndex is changed in each), there is no way to determine a priori what the expression will evaluate to (because the order of evaluation is not known).
In short, the above expression is undefined.