Question

Can somebody explain how this works? Thanks a lot :)

    define("FLAG_A", 1);
    define("FLAG_B", 2);
    define("FLAG_C", 4);
    function test_flags($flags=false) {
        if ($flags & FLAG_A) echo "A";
        if ($flags & FLAG_B) echo "B";
        if ($flags & FLAG_C) echo "C";
    }
    test_flags(FLAG_A|FLAG_B);
Was it helpful?

Solution

This is done using what is called bitwise math. Specifically, they are using the & (bitwise and) operation to check to see if a value is set. For the sake of argument here, we will use 4-bit numbers, to keep it short and simple.

The number 7, in 4-bit binary, is as follows:

0111

Each digit has a value that is doubled each time, and all of them are added together to make the total number of 7. Broken down, it works like so:

0    1    1    1
^    ^    ^    ^
|    |    |    |
8    4    2    1

So, essentially, it is:

0 * 8 + 1 * 4 + 1 * 2 + 1 * 1 = 7

Now, with bitwise math, specifically the bitwise and, we can say that we only care about bits in certain columns -- basically, the bit in each column must be 1, or it will be set to zero. So, checking for '4' inside '7' with bitwise math:

  0111 (7)
& 0100 (4)
______
  0100 (4)

Since this value is non-zero, it is true, and we can determine that the value 4 is inside the value 7. Now consider the number 11:

1    0    1    1
^    ^    ^    ^
|    |    |    |
8    4    2    1

1 * 8 + 0 * 4 + 1 * 2 + 1 * 1 = 11

Try looking for 4 in that

  1011 (11)
& 0100 (4)
______
  0000 (0)

Since it has a value of 0, it is false, and we can consider that the number (4) is not inside the number 11.

Similarly, we can conclude that numbers 4, 2, and 1, but not 8, are in 7. In 11, we have 8, 2, and 1. By treating numbers as a series of bits, instead of a singular value, we can store many flags inside a single integer.

Definitely do some more reading on bitwise math, it can be very useful when used correctly, just don't try to shoe-horn it into everything.

OTHER TIPS

This is based on bitwise operators. Think of

define("FLAG_A", 0001);  // in binary form
define("FLAG_B", 0010);
define("FLAG_C", 0100);

Hence, e.g., $flags & FLAG_A is a bitwise AND between the variable $flags and the constant FLAG_A.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top