Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shell bit shifting producing different numbers

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
like image 628
ArmenB Avatar asked Sep 19 '13 15:09

ArmenB


People also ask

What happens when you shift bits?

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.

What does bit shifting by 1 do?

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.

What is shift 2 in shell script?

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.


2 Answers

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.

like image 84
Dan Avatar answered Nov 09 '22 11:11

Dan


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!

like image 20
loreb Avatar answered Nov 09 '22 12:11

loreb