Randy> The code trinket:
Randy> unsigned char c = 0xca;
Randy> unsigned long l;
Randy>
Randy> l = c<<24;
Randy> printf("%lX\n",l);
Randy> l will be 0xFFFFFFFFCA000000 with gcc. And 0xCA000000 with cc (what I
Randy> want). gcc for osf/1 does the same, btw.
Just because another compiler does something differently does not
necessarily mean gcc is at fault. I don't have a C ref. manual handy,
but the C++ manual states:
C++ follows ANSI C in defining integral promotions as
"value-preserving." That is, a char, a short, or an int
bit field, or their signed or unsigned varieties, will
be widened to int if int can represent all the values of
the original type or to unsigned int otherwise.
Now, int certainly can represent all the values of unsigned char, so
variable c gets promoted to int. I presume the same
"value-preserving" rule applies for int->long promotion. If so,
notice that ((int)0xca000000) is a negative number. In order to
preserve this negative value, gcc thus has to pick "long int" as the
promoted type.
You get the desired result simply be saying:
l = ((unsigned)c)<<24;
Actually, unsigned long would be safer as that would work even with
shift amounts greater than 24.
--david