3
votes

From my knowledge, bitwise operators perform a check on all corresponding bits, as in:

echo 64 | 32;   //prints 96
echo 'a' & 'b'; //prints `

While conditional && and || operators perform operations on boolean values:

echo (int)(true && false); //prints: 0
echo (int)(true || false); //prints: 1

When I (in my head) want to predict the result of a bitwise operation, I first convert the values into their binary representation (which depends on the datatype). After this, I compare it bit-for-bit, and convert the result into the suitable output type (which I suppose is determined by the operands). Although at one point, I tried doing the same with boolean values, which (from my knowledge) only consists of one bit in memory, making true corresponding to 1₂, and making false corresponding to 0₂ (in binary). Performing bitwise operations on these values should therefore produce a similar result as with && and ||, right? To show you what I mean:

true & false    =>      1₂ & 0₂      =>      0₂     =>     false
true | false    =>      1₂ | 0₂      =>      1₂     =>     true
~true           =>      ~1₂          =>      0₂     =>     false

(Not including xor, as there's no corresponding conditional boolean operator.)

To me, it looks like the behaviour should be really equivalent to conditional operators:

true && false   =>      false
true || false   =>      true
!true           =>      false

So therefore, I set this code up to test it:

    echo "true AND false: " . ((true && false) ? "1" : "0") . "<br />\n";
    echo "true OR false: " . ((true || false) ? "1" : "0") . "<br />\n";
    echo "NOT true: " . ((!true) ? "1" : "0") . "<br />\n";

    echo "<br />\n";

    echo "true BITAND false: " . ((true & false) ? "1" : "0") . "<br />\n";
    echo "true BITOR false: " . ((true | false) ? "1" : "0") . "<br />\n";
    echo "BITNOT true: " . ((~true) ? "1" : "0") . "<br />\n";

It gave me the following output:

true AND false: 0
true OR false: 1
NOT true: 0

true BITAND false: 0
true BITOR false: 1

Fatal error: Unsupported operand types in C:\Abyss Web Server\htdocs\handler.php on line 21

So from this, I have two questions:

  1. What's the point with && and ||, if we (as it seems) can use & and | on boolean values instead?
  2. Why can't I do ~true (or with other words, why aren't boolean values supported)? To me, it sounds logical that ~true returns false.

I did come up with one thing, being that && and || will (sometimes) cast the values into bool and thereafter return the correct results, if we (by mistake) would happen to pass a value that's not of type bool. But to solve that, can't we just do a cast first? Such as:

if ((bool)$foo & (bool)$bar) { ...

It feels like I'm missing a major piece here that changes everything... But just in case I didn't, I included as much info as I could. Could someone make me understand this a bit better, by answering my two questions? I'm pretty confused at this point, and I've been thinking about this for quite some time.

2
Bitwise operators don't return Booleans unless they're operating on Boolean values, comparison operators always return a Boolean result.... that's one very major difference - Mark Baker
Bitwise operator on two integer values will return an integer value... e.g. (using 8 bits to simplify) 00001000 | 00000111 will return 00001111; 00001111 & 01010101 will return 00000101 - Mark Baker
@Mark Baker That's true, though that's why I was assuming that an explicit cast somewhere would be suitful (as in my last example). I mean, if conditional operators (or comparison operators) have 2 different values, they need them converted first, right? So wouldn't that cast be taken place regardless of operator? Or are there any other weak points with the last code I provided? (With other words, doesn't the 8 and the 7 be casted like this: (bool)8 | (bool)7, even if we'd use 8 || 7?) - Max
Why have the overhead of an explicit cast for a comparison when PHP will do an implicit cast to Boolean.... and once the value is Boolean, a comparison is likely to be faster than a bitwise operation - Mark Baker
Well PHP is open source, so you can always look at the source.... but the two types of operators are designed for very different purposes... bitwise operators will work on Booleans, but their strength is working on non-Booleans.... and because PHP is loose-typed, comparison operators are intended to work with any datatype.... and the behaviour of both types of operators is well documented - Mark Baker

2 Answers

4
votes

Answer 1

Parts of a boolean expressions (||, &&, !, ...) are only evaluated if needed (from left to right):

  if ($a | func()) { } // func is always called
  if ($a || func()) { } // func is not called if $a is true,
                        // because expression is true whatever func will return
  if ($a && func()) { } // func is not called if $a is false,
                        // because expression is false whatever func will return
  func() || exit(); // exit() will be called if func() returns false

Take a look at the documentation: http://php.net/manual/en/language.operators.logical.php

Answer 2

~true seems not to be meaningful: true is 0x00...01 and ~true will be 0xff...fe and not false 0x000...0:

var_dump(~((int)true)); // prints: int(-2)
echo dechex(~((int)true)); // prints: fffffffffffffffe

Use !-operator instead:

var_dump(!true); // prints: bool(false)

Résumé

Use bitwise operators only if you need to change bits.

0
votes

true and false boolean flags, albeit being stored in memory as 32-bit or 64-bit values, should be considered just as two-states boolean values. You'll end up using it only on brach guards so you should not make arithmetic over them. && and || evaluates as boolean flags, bitwise operators & and | evaluates as the same of the operands (e.g. int & int evaluates as int, int && int evaluates as boolean).

the story is: use && and || when you have to take decisions over some conditions. Use & and | to perform boolean arithmetic over values.

that's C++

C doesn't have any built-in boolean values so any non zero value is a true, and zero is false.