C bit-shifting problem

Thread Starter

odm4286

Joined Sep 20, 2009
265
The following code prints 0 to the screen. I swear it should be 1, what am I missing?
k = i shifted left by j, since i is zero this is 0 + j shifted left 0 times, since j is 1 this becomes 0 + 1

Code:
int main(void) {
        int i = 0, j = 1, k;
        k = i << j + j << i;
        printf("%d",k);
        return 0;
    }
 

danadak

Joined Mar 10, 2018
4,057
I agree, if I do each sub expression for k it gets the right answer.
But once I do the sum I also get 0, should be 1.

Also its not precedence of operators, what gives ?

Regards, Dana.
 

Thread Starter

odm4286

Joined Sep 20, 2009
265
I agree, if I do each sub expression for k it gets the right answer.
But once I do the sum I also get 0, should be 1.

Also its not precedence of operators, what gives ?

Regards, Dana.
Glad I'm not the only one that thought this was a tricky problem.
 

hexreader

Joined Apr 16, 2011
619
My detailed knowledge of C is very poor, but according to my compiler's help (mikroC pro for PIC), + has higher precedence than shift.

So zero shifted left 2 and then shifted left zero gives zero.

Maybe OP's compiler has different precedence rules to mikroC?

Or maybe I really do know nothing :(
 

Ian Rogers

Joined Dec 12, 2012
1,136
Well It make no sense.. Its been optimised out!! No addition at all..

Here's what is compiled
Code:
  movlb 0 ; select bank0
  clrf main@k
  clrf main@k+1
  lslf main@k,f
  rlf main@k+1,f
  lslf main@k,f
  rlf main@k+1,f
 
On Arduino IDE

C:
void setup() {
  Serial.begin(9600);
}

void loop() {
  int i = 0, j = 1, k;
  k = i << j + j << i;
  Serial.println(k);
  k = (i << j) + (j << i);
  Serial.println(k);
here: goto here;
}
Outputs 0 and then 1

On GCC compiler in Eclipse (for D2000)
k = i << j + j << i;
Throws an error:
Description Resource Path Location Type
suggest parentheses around '+' inside '<<' [-Werror=parentheses] main.c /AACex2 line 9 C/C++ Problem


k = (i << j) + (j << i);
Outputs 1

Edited: I see that there is a switch "Wno-parentheses". I suspect that the OP's compiler has that switch (or its analog) set. Precedence of + is higher than <<.

Edited again: and k=i << (j+j) << i; in that code evaluates to 0, as it should.
0<<2 = 0
0<<0 = 0
 
Last edited:

WBahn

Joined Mar 31, 2012
32,823
The following code prints 0 to the screen. I swear it should be 1, what am I missing?
k = i shifted left by j, since i is zero this is 0 + j shifted left 0 times, since j is 1 this becomes 0 + 1

Code:
int main(void) {
        int i = 0, j = 1, k;
        k = i << j + j << i;
        printf("%d",k);
        return 0;
    }
First this is to explicitly apply order of operations.

Since the bit shift operations are lower priority than the addition operator, you have

k = i << ( j + j ) << i;

Now since the bit shift operations are left associative, you have

k = (i << ( j + j )) << i;

So now let's evaluate it.

k = (0 << ( 1 + 1 )) << 0;
k = (0 << 2) << 0;
k = 0 << 0;
k = 0;
 

WBahn

Joined Mar 31, 2012
32,823
Oh, the thing that I was going to point out and forgot, is that the problem you had is that you interpreted the code you wrote according to the order in which you wanted the operations to be performed in instead of either looking to find out what order the operations are actually performed in (even after it wasn't doing what you wanted) or forcing the compiler to actually do them in the order you wanted. The first shortcoming is one that can only be fixed by getting in the habit of stepping back and, if necessary, looking up how a language actually specifies that things be done. But the latter shortcoming can be overcome by judicious and liberal use of parentheses in order to not give the compiler (or anyone else, including yourself, reading your code) any option but to interpret it as you intended. This is particularly true when working with operators beyond the usual arithmetic ones. So don't rely on the order of operations being what you want, make it so that the order of operations simply don't matter.
 
Top