Search code examples
cbit-shiftinteger-promotion

How is shift operator evaluated in C?


I recently noticed a (weird) behavior when I conducted operations using shift >> <<!

To explain it, let me write this small runnable code that does two operations which are supposed to be identical(In my understanding), but I'm surprised with different results!

#include <stdio.h>

int main(void) {
    unsigned char a=0x05, b=0x05;

    // first operation
    a = ((a<<7)>>7);

    // second operation
    b <<= 7;
    b >>= 7;

    printf("a=%X b=%X\n", a, b);
    return 0;
} 

When ran, a = 5 and b = 1. I expect them both to be equal to 1! Can someone kindly explain why I got such a result?

P.S: In my environment the size of unsigned char is 1 byte


Solution

  • The shift operations would do integer promotions to its operands, and in your code the resulting int is converted back to char like this:

    // first operation
    a = ((a<<7)>>7); // a = (char)((a<<7)>>7);
    
    // second operation
    b <<= 7; // b = (char) (b << 7);
    b >>= 7; // b = (char) (b >> 7);
    

    Quote from the N1570 draft (which became the standard of C11 later):

    6.5.7 Bitwise shift operators:

    1. Each of the operands shall have integer type.
    2. The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

    And it's supposed that in C99 and C90 there are similar statements.