Search code examples
cshortunsigned-integerbit-shift

Why are x and z evaluating differently if "x=(date<<7)>>12" and {y=date<<7;z=y>>12;}?


It is really frustrating.What is the possible reason that (date<<7)>>12 is giving a different result from y>>12 where y is date<<7?.I should add that the latter is working correctly as I intend,but the first is not.What's the difference?I can see none.

#include<stdio.h>

int main()
{
unsigned short date=5225,x,y,z;
x=(date<<7)>>12;
printf("Month is %hu\n",x);
y=date<<7;
z=y>>12;
printf("Month is %hu\n",z);

}

OUTPUT

Month is 163

Month is 3


Solution

  • In C, all integer computations are promoted to at least int1. So

    x = (date << 7) >> 12
      = (5225 << 7 /* result as int */) >> 12
      = 668800 >> 12
      = 163
    

    after the computation is complete, we truncate the result back to an unsigned short to get 163.

    In the second case, the y forced the result to be truncated to be an unsigned short, so

    y = (unsigned short) (date << 7)
      = (unsigned short) 668800
      = 13440
    z = y >> 12
      = 3
    

    1: C11 §6.5.7/3: "The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand."; §6.3.1.1/2: "If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions."