Re: busybox zcat errors
Richard Hirst <rhirst@linuxcare.com> writes:
> int main()
> {
> unsigned char buf[4] = { 0xe9, 0x6c, 0xcf, 0x45 };
> unsigned long crc = 0x169330baL;
>
> printf("buf = %x\n", buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]);
> printf("crc ^ 0xffffffffL = %lx\n", (crc ^ 0xffffffffL));
> if ((buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) != (crc ^ 0xffffffffL))
> printf("Oops!\n");
>
> return 0;
> }
I believe this is a program bug. This is what happens according
to C integral promotion rules in the expression inside the "if".
1) buf[0], buf[1] etc. are promoted to int, and notice that this is
a signed int, even though your chars are unsigned.
Quoting from a fairly old reference..
"A char, short int, or int bit field, either signed or unsigned, or an
object that has enumeration type, can be used in an expression wherever
an int or unsigned int is permitted. If an int can represent all values
of the original type, the value is converted to an int. Otherwise, it
is converted to an unsigned int. These conversion rules are called the
integral promotions."
That leaves us with an int of value 0xe96ccf45 on the LHS of the "!=".
2) The RHS is evaluated, with the resultant type an unsigned long of
value 0x00000000e96ccf45.
3) The LHS (a negative int) is promoted to unsigned long so that the LHS
and RHS of the "!=" have the same type. This is a two step process,
first converting to signed long, then to unsigned long. The int to
signed long conversion results in a value of 0xffffffffe96ccf45.
"When a signed integer is converted to an unsigned integer of equal or
greater size, and the signed integer value is nonnegative, its value
is unchanged. If the signed integer value is negative, then:
* If the unsigned integer type is larger, the signed integer is
first promoted to the signed integer that corresponds to the
unsigned integer; then the value is converted to unsigned by
adding to it one greater than the largest number that can be
represented in the unsigned integer type.
* If the unsigned integer type is equal or smaller than the signed
integer type, then the value is converted to unsigned by adding
to it one greater than the largest number that can be represented
in the unsigned integer type."
You can fix the problem by casting the LHS to unsigned int.
--
Alan Modra
Reply to: