  beginning_php thread: Explain the Shift thing to me? ( << and >> )

 Message #1 by "Dan Ostrowski" on Mon, 20 May 2002 14:05:43
```I am not sure how to wrap my brain around it.  Does it have something to
do with the number of bits in an argument?  I am not even sure i get THAT.

I have read the documentation on it, but it doesn't make too much sense to
me. PLUS there is this code i am reading over right now...

<?php

// define helper constants

define('LOCAL'        1 << 0);
define('REMOTE'       1 << 1);
define('TO_LOCAL',    LOCAL);
define('TO_REMOTE',   REMOTE);
define('FROM_LOCAL',  LOCAL << 2);
define('FROM_REMOTE', REMOTE << 2);

//go on to do FTP class coding

?>

this is from the ProPHP4 book.  Why are they using these operators?

Thanks for any help,

regards,

dan```
 Message #2 by "Nikolai Devereaux" on Mon, 20 May 2002 10:22:41 -0700
```Shift operators shift bits to the left or right.  They essentially perform
multiplications or divisions by powers of two, but they do it in one

Let's take a number, 42, which is 00101010 in binary.

Shift that to the left two bits (42 << 2) we get 10101000.  Get it?  Now
what did we really do here?  If we convert that number to decimal we get
168.

168 = 42 * 4.  or more appropriately,
168 = 42 * (2^2)
+--->  (The number of positions shifted)

each time we shift a bit to the left, we multiply by two.  Each time we
shift to the right, we divide by two.

(42 >> 1) = 00010101.  Convert to decimal, and you get 21 as expected.

Now, on to the PHP side of things:

> define('LOCAL'        1 << 0);
> define('REMOTE'       1 << 1);
> define('TO_LOCAL',    LOCAL);
> define('TO_REMOTE',   REMOTE);
> define('FROM_LOCAL',  LOCAL << 2);
> define('FROM_REMOTE', REMOTE << 2);

This is just the author's way of defining unique named constants.  When all
is said and done, you'll end up with this:

VAR          DECIMAL   BINARY
LOCAL           1         0001
REMOTE          2         0010
TO_LOCAL        1         0001
TO_REMOTE       2         0010
FROM_LOCAL      4         0100
FROM REMOTE     8         1000

From the context, the only four values that make sense are the TO_xx and
FROM_xx values.  Notice that they are not only unique, but each has only one
bit set in their binary representation.  This is a common practice in
setting up bitmasks -- where each bit set in a number represents something.

The most common bitmask you'll see is a 9-bit mask used in unix permissions.

rwxrwxrwx is the "ls -l" representation of the binary number 111111111
(decimal 511).

Each number between 0 and 511 (inclusive) specifies a different permission
range for the user, group, and world for a file or directory.

Let's go back to 42 (00101010).  Let's add a leading 0 to make it a nine bit
representation (This is fine -- decimal 0000004 is still 4)

000101010
---r-x-w-

That file (oddly enough, i know) has no permissions set for the owner, read
and execute permissions for the group, and write permissions for the world.
(Sounds like my public_html dir... =\)

Hope this helps,

Nik

```
 Message #3 by "Dan Ostrowski" on Mon, 20 May 2002 21:45:17
```As always, thanks a lot Nik!

I was reading over the documentation online and THIS was really the thing
that was stumping me:

-----------------------------------------
Bit shifting (at least in PHP4) seems to preserve the sign, except that a 1
shifted to the sign bit makes a positive number negative. Examples:
echo ( 1 << 2 ); // Returns 4
echo ( -1 << 2 ); // Returns -4
echo ( -3 >> 1 ); // Returns -2
echo ( 1 << 31 ); // Returns -2147483648
echo ( (1<<31) >> 31 ); // Returns -1 [negative sign bit
preserved on right shift].
echo (-1 >> 100); // Returns -1 [-1>>X = -1 for all X].
-----------------------------------------

this was the one that was making me unsure about most of it:

echo ( 1 << 31 ); // Returns -2147483648

how does this get turned negative?

anyhow it makes a lot more sense now, thank you very much!

Dan```
 Message #4 by "Nikolai Devereaux" on Mon, 20 May 2002 14:58:34 -0700
```Okay -- positive and negative numbers are not represented the same way with
just a sign bit differentiating them.  They're stored in two's complement
notation.

<aside>
Are you familiar with this?  If not, the gist of it is that to go from
negative to positive (or vice versa), flip all the bits and add 1.

4 = 0000 0100

-4 = 1111 1011 (flip bits)
-----------
1111 1100 (result)
</aside>

Anyway, the PHP interpreter seems to use logical right-shifting, which means
that if the highest bit is 1 and you shift right, it shifts in a 1 to
preserve sign.  If it's 0, shift in 0.

I'll show you the (16-bit) before/after of these shifts to make more sense.

BEFORE                          AFTER

> echo ( 1 << 2 ); // Returns 4
00000000 00000001               00000000 00000100

> echo ( -1 << 2 ); // Returns -4
11111111 11111111               11111111 11111100

> echo ( -3 >> 1 ); // Returns -2
11111111 11111101               11111111 11111110

> echo ( 1 << 15 ); // Returns -32768
(pretend it's being shifter 15 instead of 31)
00000000 00000001               10000000 00000000

> echo ( (1<<15) >> 15 ); // Returns -1 [negative sign bit
> preserved on right shift].
the first part returns 100...0
shifting back 15 bits returns   11111111 11111111

hth,

nik

```
 Message #5 by "Dan Ostrowski" on Mon, 20 May 2002 23:45:40
```it does.  very much.

i think i need to look into bitwise stuff a bit more... i hate being a
n00b on this kind of stuff... =)

thanks again, as always, Nik.

regards,
dan```
 Message #6 by "Nikolai Devereaux" on Mon, 20 May 2002 17:36:29 -0700
```As always, It's my pleasure.

take care,

nik

```  