We found some strange values being produced, a small test case is below.
This prints “FFFFFFFFF9A64C2A” . Meaning the unsigned long long seems to have been sign extended.
But why ?
All the types below are unsigned, so what’s doing the sign extension ? The expected output
would be “F9A64C2A”.
#include <stdio.h>
int main(int argc,char *argv[])
{
unsigned char a[] = {42,76,166,249};
unsigned long long ts;
ts = a[0] | a[1] << 8U | a[2] << 16U | a[3] << 24U;
printf("%llX\n",ts);
return 0;
}
In the expression
a[3] << 24U, thea[1]has typeunsigned char. Now, the “integer promotion” converts it tointbecause:((draft) ISO/IEC 9899:1999, 6.3.1.1 2)
Please note also that the shift operators (other than most other operators) do not do the “usual arithmetic conversions” converting both operands to a common type. But
(6.5.7 3)
On a 32 bit platform,
249 << 24 = 4177526784interpreted as aninthas its sign bit set.Just changing to
fixes the issue (The suffix
Ufor the constants has no impact).