0

I've been struggling with the shift operator in PHP, assuming that it precedes arithmetic operations like +, 1 etc. I've been unable to find any definition of this in the php manual.

Let's say that I have the value 1, which I want to 3, then to 7 etc., filling bits from the right (LSB).

I tried:

$X = 1;

Then, in a loop:

$X <<= 1 + 1; // returns 4 instead of 3.
$X <<= 1 + 1; // returns 16 instead of 7.

So evidently 1+1 is calculated BEFORE the shift. My solution:

$X = 1;
$X <<= 1; // $X=2
$X += 1;  // $X=3 as expected
$X <<= 1; // $X=6
$X += 1;  // $X=7 as expected

Which is a bit more clumsy, but this returns the right numbers. Shouldn't the first method produce the correct result, shifting first and THEN do the arithmetic?

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • 2
    `+` is higher precedence https://www.php.net/manual/en/language.operators.precedence.php Use `($X <<= 1) + 1;` – AbraCadaver Jun 27 '19 at 18:23

3 Answers3

2

$X <<= 1 + 1

is converted into:

$X = $X << (1 + 1)

if you want to do it differently, then you can use:

$X = ($X << 1) + 1

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
0

See the Operator Precedence table and explanations. The + operator is higher precedence than <<=. You can force precedence by grouping with parentheses ():

$X = ($X <<= 1) + 1;

Also note:

Use of parentheses, even when not strictly necessary, can often increase readability of the code by making grouping explicit rather than relying on the implicit operator precedence and associativity.

AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • for short assignment forms, higher precedence of `+` does not matter (what `$x = 2;$x *= 2+3;` will return?, also - there is no sense in double assignment – Iłya Bursov Jun 27 '19 at 18:35
  • WTF are you talking about? That returns 10 obviously because `+` higher precedence than `*=`. – AbraCadaver Jun 27 '19 at 18:38
  • I'm talking about associativity, operators like `a op= b` are executed with right associativity, which basically means that they are treated like `a = a op (b)` and this is why precedence does not matter here, also `($X <<= 1) + 1;` will not work for op – Iłya Bursov Jun 27 '19 at 18:48
  • Associativity only applies when precedence is the same, so yes, precedence does matter here as the precedence is not the same. – AbraCadaver Jun 27 '19 at 18:53
0

Thanks for your comments! Actually, '<<=' is not only an operator, but also an assignment, so

$X <<= 1 + 1 will be interpreted as $X <<= 2.
$X = $X << 1 + 1 might possibly work (I haven't checked), but
$X = ($X << 1) + 1 as suggested by Ilya would be the right way.