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.
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.
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.
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 .
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?
qT |= (unsigned long long)readb() << (shiftvalue & 63); This will be perfect solution assuming u dont requiered more than 63 bit shift
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With