Reputation: 1331
I originally had the following code where it
is a void**
:
while (it != end)
{
*it = *(it + 1);
it++;
}
I decided to change it + 1; it++;
to ++it;
because I was calculating the same value twice.
while (it != end)
{
*it = *(++it);
}
However, after doing so, my program no longer functions the same way.
Edit: I would like to note that this is not i = i++;
, but rather assigning the value pointed to by it
to the value in front of it.
Upvotes: 7
Views: 153
Reputation: 222660
In *it = *(++it);
, the compiler might evaluate it
for the purposes of preparing the reference *it
and, after that, perform the side effect of incrementing it
for ++it
. Or it might do the side effect first and then evaluate it
for the *it
. The C standard does not say in which order these must occur. The assignment itself, storing a value in *it
, must be later, but that is something else. The compiler can work on parts of the left side and parts of the right side in any order it wants.
You are not allowed both modify an object (++it
) and use it (in *it
) without a determined order between them. Doing so results in undefined behavior. This is per C 2011 [N1570] 6.5 2:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
Incrementing it
in ++it
is a side effect, and using it
in *it
is a value computation using the value of it
, which is a scalar object. Therefore, the behavior is undefined.
Upvotes: 4
Reputation: 85767
C99, 6.5 Expressions:
- 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.
(Emphasis mine.)
In
*it = *(++it);
We read twice and store once. *it
on the left side reads from it
; ++it
on the right side reads from and stores to it
. There are no sequences points here.
This expression has undefined behavior because the read on the left side is not used to determine the value to be stored.
*it = *(it + 1);
is allowed because it
is not modified here (there are no stores), so you can have as many reads as you want.
Upvotes: 2