views:

150

answers:

8

I have the following code that I'm reading through:

if( (i%2) == 0 ){ 
    *d = ((b & 0x0F) << 4); 
}
else{
    *d++ |= (b & 0x0F); 
};

I'm looking specifically at the else statement and wondering in what order this occurs? I don't have a regular C compiler, so I can't test this. When we are performing *d++ |= (b & 0x0F);, what order does this occur in?

+11  A: 

The ++ is applied on the pointer d, not on the lvalue that is being assigned to, *d.

If you really want to, you can think of it like this:

  1. The value of b is bitwise-AND:ed with the constant 0x0f
  2. The resulting bit pattern is bitwise-OR:ed into the value that d points at.
  3. The pointer d is incremented to point at the next value.
unwind
So moving to the next location from the pointer happens AFTER all of the operations are applied to the original location. Great, thanks.
chris
Not necessarily; the semantics of the postfix operator `++` are that the side effect is applied sometime before the next sequence point, but exactly when that happens is not specified. The compiler may store the result of `*d` into a temporary and immediately increment `d` before doing anything else.
John Bode
@John: Exactly, that's why I wrote "if you really want to".
unwind
A: 

This link (C++ Operator Precedence) should give you the answer.

Ondrej Slinták
+2  A: 

First the right part of |= is executed, then the *d |= assignment is done, then d is incremented. Usually when you have code that causes questions like that you should just rewrite it for the sake of clarity.

sharptooth
+5  A: 

d++ returns the value d had before it was incremented. This is then dereferenced by the *, and that location is what the |= is performed on. So the data at the location prior to incrementing d will have (b & 0x0F) ored into it.

In general, if the order of operations in a line of code is not clear at a glance, refactor the line into its constituent operations until it is. Generated code does not become any faster or more compact simply from squeezing lots of operations onto one line of C! There is no good reason to sacrifice comprehensibility in this way. Replace the line with

*d |= (b & 0x0F); 
d++;
moonshadow
Agreed. Unfortunately, this is only a really small portion of a ~10,000 line script that all looks very similar..
chris
A: 

++ is done first. However post-increment (i.e. d++ here) is equivalent to this (temp=d, d++, temp).

Chris Henry
+2  A: 

++ will occur before |=. Assignment operators are at the bottom of the precedence chart.

Covar
A: 

According to http://www.cppreference.com/wiki/operator_precedence

it will evaluate (b & 0x0F) then apply the |= to it and assign it to *b, finally increment the value that *b in pointing to.

StudiousJoseph
`|=` has nearly the lowest precedence, how do you figure it will be evaluated before the increment operator, which has nearly the highest precedence?
meagar
A: 

The expression *d++ |= (b & 0x0F) breaks down as follows:

  1. The expressions *d++ and b & 0x0F are each evaluated once (the order in which they are evaluated is not specified; the compiler is free to evaluate b & 0x0F before *d++ since the result does not depend on the order in which evaluation occurs);
  2. The result of (b & 0x0F) is bitwise-or'd with the result of *d++;
  3. The result of the bitwise-or operation is stored to the location originally pointed to by d;
  4. At some point in all of this, the value of d is updated.

The expression *d++ is parsed as *(d++); i.e. you are dereferencing the result of the expression d++. The expression d++ evaluates to the current value of d, and at some unspecified point before the next sequence point (in this case, the end of the statement), the value of d is updated. The side effect of updating d does not have to be applied immediately; it can occur before or after the assignment.

John Bode