views:

156

answers:

3

I'm not familiar with bitwise operators, but I have seem them used to store simple settings before.

I need to pass several on/off options to a function, and I'd like to use a single integer for this. How can I go about setting and reading these options?

+1  A: 

the idea is not good, really. you would better pass few boolean. if you want use bitwise then

function someFunc($options)
{

   if ($options & 1 != 0)
      //then option 1 enabled
   if ($options & (1 << 1) != 0)
      //then option 2 enabled      
   if ($options & (1 << 2) != 0)
      //then option 3 enabled      
}
Andrey
The `!= 0`'s are not needed.
Kendall Hopkins
@Kendall Hopkins "Explicit is better than implicit." says you Zen of Python ;)
Andrey
+5  A: 

You sure can do it in PHP.

Let's say you have four booleans you want to store in a single value. That means we need four bits of storage space

0000

Each bit, when set individually, has a unique representation in decimal

0001 = 1 // or 2^0
0010 = 2 // or 2^1
0100 = 4 // or 2^2
1000 = 8 // or 2^3

A common way to implement this is with bit masks to represent each option. PHP's error levels are done this way, for example.

define( 'OPT_1', 1 );
define( 'OPT_2', 2 );
define( 'OPT_3', 4 );
define( 'OPT_4', 8 );

Then when you have an integer that represents 0 or more of these flags, you check with with the bitwise and operator which is &

$options = bindec( '0101' );
// can also be set like this
// $options = OPT_1 | OPT_3;

if ( $options & OPT_3 )
{
  // option 3 is enabled
}

This operator works as such: only bits that are set in both operands are set in the result

0101 // our options
0100 // the value of OPT_3
----
0100 // The decimal integer 4 evaluates as "true" in an expression

If we checked it against OPT_2, then the result would look like this

0101 // our options
0010 // the value of OPT_2
----
0000 // The decimal integer 0 evaluates as "false" in an expression
Peter Bailey
Thanks for breaking everything down.
Andrew M
+4  A: 

It works pretty much the same way in both languages, a side by side comparison:

C:

#include <stdio.h>
#include <stdint.h>

#define FLAG_ONE 0x0001
#define FLAG_TWO 0x0002
#define FLAG_THREE 0x0004
#define FLAG_FOUR 0x0008
#define FLAG_ALL (FLAG_ONE|FLAG_TWO|FLAG_THREE|FLAG_FOUR)

void make_waffles(void)
{
   printf("Yummy! We Love Waffles!!!\n");
}

void do_something(uint32_t flags)
{
    if (flags & FLAG_TWO)
         make_waffles();
}

int main(void)
{
    uint32_t flags;

    flags |= FLAG_ALL;

    /* Lets make some waffles! */
    do_something(flags);

    return 0;
}

PHP:

<?php

define("FLAG_ONE", 0x0001);
define("FLAG_TWO", 0x0002);
define("FLAG_THREE", 0x0004);
define("FLAG_FOUR", 0x0008);
define("FLAG_ALL", FLAG_ONE|FLAG_TWO|FLAG_THREE|FLAG_FOUR);

function make_waffles()
{
    echo 'Yummy! We Love Waffles!!!';
}

function do_something($flags)
{
    if ($flags & FLAG_TWO)
       make_waffles();
}

$flags |= FLAG_TWO;
do_something($flags);

?>

Note, you don't absolutely need to use constants, I just use them out of habit. Both examples will run, I compiled the C version via gcc -Wall flags.c -o flags. Change flags in either example to anything but FLAG_TWO or FLAG_ALL and (sadly) no waffles will be made.

Tim Post
Great, this example is very understandable. I've been trying to figure out bitwise operators for a while now. Thanks for having the code both in PHP and C, since I'll be using both for this.
Andrew M
No problem. @Peter Bailey provided the best answer, I'm glad you accepted his.
Tim Post
They're both really good answers. I tried to accept both, didn't work.
Andrew M
@Andrew M - I fixed the C example so its the same as the PHP example, and made sure you could actually compile and run it.
Tim Post