in my local machines bash when I run:
echo $((192 << 24))
3221225472
but on my embedded targets busy box SHELL I get something else:
echo $((192 << 24))
-1073741824
it works when I left shift by a smaller number though. The embedded device is 64bit, where my local host is 32 bit.
Just to be clear, on the 32bit machine, the value is positive, on the 64 bit machine it's negative.
EDIT: This is on the embedded device which is 64 bit machine with SHELL. It doesn't happen when left shifting by 23.
echo $((192 << 23))
1610612736
echo $((192 << 24))
-1073741824
On the local host, which is a 32 machine with BASH:
echo $((192 << 55))
6917529027641081856
echo $((192 << 56))
-4611686018427387904
Logical bit shifting may be useful for multiplying or dividing unsigned integers by powers of two. For example, if the value "0001" or "1" is shifted left, it becomes "0010" or "2," shifted to the left again it becomes "0100," or "4." Shifting to the right has an opposite effect of dividing the value by two per shift.
Bitshifting shifts the binary representation of each pixel to the left or to the right by a pre-defined number of positions. Shifting a binary number by one bit is equivalent to multiplying (when shifting to the left) or dividing (when shifting to the right) the number by 2.
If a parameter is shifted to a position with a number less than 1, it "falls off" — its value is discarded. So the command shift always discards the previous value of $1, and shift 2 always discards the previous values of $1 and $2.
The binary representation of 192
is 11000000
. When you shift it left 24 places, the only two bits which are set are the two most significant bits - the representation is 11000000 00000000 00000000 00000000
. When a 32 bit system sees the most significant bit set, it interprets it as a negative number in "two's complement" format. For a 64 bit system, the most significant bit is still zero, so it is interpreted as a positive number.
This is simply an integer overflow on the 32 bit machine. You could expect the same behavior in C or any other language when using 32 vs 64 bit signed integer types.
POSIX (here) says "Only signed long integer arithmetic is required", and in C a long is at least 32 bits; that being said, some shells explicitly choose a fixed width, eg mksh uses 32 bits arithmetic, and peeking at the busybox' source (math.h) it seems like they only use 64 bits is ENABLE_SH_MATH_SUPPORT_64 is #define'd, regardless of whether the underlying system is 32/64 bits. If anyone knows better, speak up!
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