Reputation: 133
I have the following piece of code:
long int compute_data_length(unsigned char* buf, int data_offset) {
long int len;
if(!buf)
return -1;
switch(data_offset) {
case 2: {
len = (buf[2] << 8) | buf[3];
}
break;
case 8: {
len = (buf[2] << 56) |
(buf[3] << 48) |
(buf[4] << 40) |
(buf[5] << 32) |
(buf[6] << 24) |
(buf[7] << 16) |
(buf[8] << 8) |
(buf[9] );
}
break;
default: len = -1; break;
}
return len;
}
When I compile, I get the following warning:
math_fun.c:240:21: warning: left shift count >= width of type [enabled by default] len = (buf[2] << 56) | ^ math_fun.c:241:27: warning: left shift count >= width of type [enabled by default] (buf[3] << 48) | ^ math_fun.c:242:27: warning: left shift count >= width of type [enabled by default] (buf[4] << 40) | ^ math_fun.c:243:27: warning: left shift count >= width of type [enabled by default] (buf[5] << 32) |
How do I fix the warning?
Upvotes: 1
Views: 7146
Reputation: 241791
Integer promotions turn buf[2] << 56
into (int)buf[2] << 56
[Note 1], but it is entirely possible that int
only has 32 bits and you need it to be an unsigned 64-bit type for the shift to be meaningful.
You're expecting unsigned long
to be 64 bits, but it might not be. It would be better to include <stdint.h>
and use uint64_t
. In any event, you need to explicitly cast the left operands of thE left shift:
((uint64_t)buf[2] << 56) | ...
[Note 1]: It's theoretically possible for unsigned char
to be as wide as an int
, in which case the integer promotion would be to an unsigned int
. But that only happens on unusual architectures.
Upvotes: 5
Reputation: 45664
Please learn to read warnings:
math_fun.c:240:21: warning: left shift count >= width of type [enabled by default] len = (buf[2] << 56) | ^
That gives you all the info you need to comprehend your error and how to remedy it:
The type you shift is less than 56 bits long, so shifting 56 bits or more is undefined behavior.
Cast to an appropriately bigger type first.
I hope long
fits the bill on your platform, because that's the type of the variable you later assign the result to. int64_t
would be guaranteed to be big enough, if it is provided.
While you are at it, consider using only unsigned
types there, overflow on signed
types is undefined.
Upvotes: 0