Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shift count negative or too big error - correct solution?

Tags:

I have the following function for reading a big-endian quadword (in a abstract base file I/O class):

unsigned long long File::readBigEndQuadWord(){
  unsigned long long qT = 0;
  qT |= readb() << 56;
  qT |= readb() << 48;
  qT |= readb() << 40;
  qT |= readb() << 32;
  qT |= readb() << 24;
  qT |= readb() << 16;
  qT |= readb() << 8;
  qT |= readb() << 0;
  return qT;
}

The readb() functions reads a BYTE. Here are the typedefs used:

typedef unsigned char   BYTE;
typedef unsigned short  WORD;
typedef unsigned long   DWORD;

The thing is that i get 4 compiler warnings on the first four lines with the shift operation:

warning C4293: '<<' : shift count negative or too big, undefined behavior

I understand why this warning occurs, but i can't seem to figure out how to get rid of it correctly. I could do something like:

qT |= (unsigned long long)readb() << 56;

This removes the warning, but isn't there any other problem, will the BYTE be correctly extended all the time? Maybe i'm just thinking about it too much and the solution is that simple. Can you guys help me out here? Thanks.

like image 427
PeterK Avatar asked Jun 11 '10 07:06

PeterK


People also ask

What is negative shift?

Negative shift counts are illegal and cause a ValueError to be raised. A left shift by n bits is equivalent to multiplication by pow(2, n). A long integer is returned if the result exceeds the range of plain integers.

Can you shift by a negative number in C?

Although shifting a negative number of bits or shifting a number of bits greater than or equal to the width of the promoted left operand is undefined behavior in C, the risk is generally low because processors frequently reduce the shift amount modulo the width of the type.

Can bit shift negative?

Details. The result of a shift operation is undefined if additive-expression is negative or if additive-expression is greater than or equal to the number of bits in the (promoted) shift-expression .


2 Answers

Your way of removing the warning is correct. As you probably do already know, the warning is occurring because you're trying to shift the contents of a byte beyond the boundaries of a word, then store it in the quadword. This operation is undefined. (It will evaluate the right-side of the assignment before assigning the value.) By explicitly casting first, there is now enough space to do the shift, so there's nothing to complain about.

Arguably, the compiler should be able to figure out you're going to store it in the quadword, so it should allocate a quadword first and do the shift there, but it might not have been made smart enough to figure it out.

Also, I'm not sure about this, but possibly compiling this for x64 will also not generate the warning, as one word is 64 bits?

like image 149
lc. Avatar answered Oct 04 '22 22:10

lc.


qT |= (unsigned long long)readb() << (shiftvalue & 63); This will be perfect solution assuming u dont requiered more than 63 bit shift

like image 32
vijayky88 Avatar answered Oct 04 '22 20:10

vijayky88