Shift count negative or too big error - correct solution?

PeterK picture PeterK · Jun 11, 2010 · Viewed 12.8k times · Source

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.

Answer

lc. picture lc. · Jun 11, 2010

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?