54
votes

I am confused with & and &&. I have two PHP books. One says that they are same, but the another says they are different. I thought they are same as well.

Aren't they same?

6
They are both the same thing, they're just used for two different things to accomplish the same task.animuson♦

6 Answers

99
votes

& is bitwise AND. See Bitwise Operators. Assuming you do 14 & 7:

    14 = 1110
     7 = 0111
    ---------
14 & 7 = 0110 = 6

&& is logical AND. See Logical Operators. Consider this truth table:

 $a     $b     $a && $b
false  false    false
false  true     false
true   false    false
true   true     true
58
votes

The other answers are correct, but incomplete. A key feature of logical AND is that it short-circuits, meaning the second operand is only evaluated if necessary. The PHP manual gives the following example to illustrate:

$a = (false && foo());

foo will never be called, since the result is known after evaluating false. On the other hand with

$a = (false & foo());

foo will be called (also, the result is 0 rather than false).

7
votes

Matthew's answer about how Logical And && operator is the biggest difference; logical comparison will stop when it will find something that breaks the chain. In addition, one more big difference it the result type/value.

tl;dr

By using the Logical And &&, it will always return a Boolean type/value, true or false.

false & 1 // int(0)
false && 1 // bool(false)

It is important to use Boolean type/values when returning a function with a logical result, because someone can use the Identical comparison operator === to compare the results (which is high likely to happen) and it will fail if you use something like this:

(false & 1) === false // bool(false)
(true & true) === true // bool(false)

Never use Bitwise And & when you need to make a logical comparison and especially when returning values from functions with logical results. Instead use the Logical And &&:

(false && 1) === false // bool(true)
(true && true) === true // bool(true)

When comparing characters, Logical And && will always result to true, even with NUL character, unless if it's converted to an integer:

'A' && 'B' // bool(true)
'A' && 0 // bool(false)
'A' && '\0' // bool(true)
'A' && (int)'\0' // bool(false)

If you use the Bitwise And & with characters, it will result the character corresponding to the Bitwise And operation between those two characters:

'A' & 'B' // string(1) "@"

01000001 // ASCII 'A'
&
01000010 // ASCII 'B'
=
01000000 // ASCII '@'

Beware the usage of the Bitwise And & when using with types other than Integers and Characters (which are special kind of integers). For example, if you use it with real numbers float/double, then it can result to 0 even if both operands are NOT 0:

1.0 & 1.0 // int(1)
2.0 & 1.0 // int(0)

1.0 && 1.0 // bool(true)
2.0 && 1.0 // bool(true)

In addition, if we go at assembly instructions level, we can see that difference and how the compiler manages to handle so the Logical And && uses cmp <var>, 0 to compare and does not continue executing if one operand fails; Bitwise And uses and <var1>, <var2> to make a bitwise result and then test if it's of 0 value. I know this question is tagged for and behavior may be different than , but I'll use a small program to demonstrate how compiler behaves when using Logical and Bitwise And.

Let's assume we have a program in that uses both Bitwise and Logical And:

int a = 0;
int b = 1;
int c = 2;

if (a & b)
    c = 3;

if (a && b)
    c = 4;

The compiler will generate the following assembly opcodes (W32Dasm result for x86; I have changed the memory addresses with <variable> names for simplicity and to be more understandable):

:0229  mov <a>, 0
:0230  mov <b>, 1
:0237  mov <c>, 2
// if (a & b) begins
:023E  mov eax, <a>
:0241  and eax, <b>        // a bitwise and b, result stored to eax
:0244  test eax, eax       // test eax and set ZeroFlag if equals to 0
:0246  je 024F             // >---  Jump if ZeroFlag is set
:0248  mov <c>, 3          //    |  or set c = 3
// if (a && b) begins            |
:024F  cmp <a>, 0          // <---  compare a to 0 and sets ZeroFlag if difference is 0
:0253  je 0262             // >---  Jump if ZeroFlag is set (a == 0)
:0255  cmp <b>, 0          //    |  compare b to 0 and sets ZeroFlag if differemce is 0
:0259  je 0262             //    |  >--- Jump if ZeroFlag is set (b == 0)
:025B  mov <c>, 4          //    |     | or set c = 4
:0262  <program continues> // <---  <---

The compiler not only uses different instructions to compare between the Logical and Bitwaise And, but at the line :0253 in if (a && b) logical comparison, we see that if a == 0 then it jumps and does not check for the rest operands.

So, I disagree to animuson's comment:

They are both the same thing, they're just used for two different things to accomplish the same task. – animuson Mar 4 '10 at 1:42

They are not the same thing and both are/(should be) used for specific tasks depending on the programs' logic/flow.

5
votes
 

AND operation: 

& -> will do the bitwise AND operation , it just doing operation based on
      the bit values. 
&&   -> It will do logical AND operation. It is just the check the values is 
       true or false. Based on the boolean value , it will evaluation the 
       expression 
3
votes

As the others are saying, a single & is bit-wise. It basically converts the left-hand value into its bits representation, and the right hand side into bits representation as well, then performs logical AND between them and outputs the result.

Double && is either true or false, (in some languages 0 or 1) if both left and right side are true (or non-zero).

I'd also add that this is not just in PHP. It is like that in many many other languages as well, like C, Java, Ruby, etc.

0
votes

&& is & performed on operands reduced to either 1 or 0.

(In other words, && is a bitwise operator under the caveat that it changes its operands. That is, logical operations are a subset of bitwise operations.)