Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do shift operations always result in a signed int when operand is <32 bits

Tags:

c#

bit-shift

Why do shift operations on unsigned ints give an unsigned result, but operations on smaller unsigned operands result in a signed int?

int signedInt = 1;
int shiftedSignedInt = signedInt << 2;

uint unsignedInt = 1;
uint shiftedUnsignedInt = unsignedInt << 2;     //OK. unsigned result

short signedShort = 1;
int shiftedsignedShort = signedShort << 2;

ushort unsignedShort = 1;
uint shiftedUnsignedShort = unsignedShort << 2; //CS0266: Can't cast int to uint

sbyte signedByte = 1;
int shiftedSignedByte = signedByte << 2;

byte unsignedByte = 1;
uint shiftedUnsignedByte = unsignedByte << 2;   //CS0266: Can't cast int to uint
like image 446
GazTheDestroyer Avatar asked Feb 09 '12 11:02

GazTheDestroyer


1 Answers

The shift operators are predefined only for these cases (shift left):

int operator <<(int x, int count);  (1)
uint operator <<(uint x, int count); (2)
long operator <<(long x, int count);  (3)
ulong operator <<(ulong x, int count); (4)

The expression uint shiftedUnsignedShort = unsignedShort << 2 is interpreted as (1)-st case (implicit up-casting from ushort to int and (int)2), so it performed a warning on illegal casting (there is no implicit cast from int result to ushort).
The same situation we can see for uint shiftedUnsignedByte = unsignedByte << 2. It also interpreted as (1)-st case (implicit up-casting from byte to int and (int)2 ,but no implicit cast of resulting value to uint).

You can resolve these issues using the following approach:

uint shiftedUnsignedShort = (uint)unsignedShort << 2  //force use the (2)-nd shift operator case  
uint shiftedUnsignedByte = (uint)unsignedByte << 2;   //force use the (2)-nd shift operator case
like image 68
DmitryG Avatar answered Sep 23 '22 11:09

DmitryG