views:

151

answers:

5

While reading some documentation here, I came across this:

unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
NSDateComponents *comps = [gregorian components:unitFlags fromDate:date];

I have no idea how this works. I read up on the bitwise operators in C, but I do not understand how you can fit three (or more!) constants inside one int and later being able to somehow extract them back from the int? Digging further down the documentation, I also found this, which is probably related:

typedef enum {
   kCFCalendarUnitEra = (1 << 1),
   kCFCalendarUnitYear = (1 << 2),
   kCFCalendarUnitMonth = (1 << 3),
   kCFCalendarUnitDay = (1 << 4),
   kCFCalendarUnitHour = (1 << 5),
   kCFCalendarUnitMinute = (1 << 6),
   kCFCalendarUnitSecond = (1 << 7),
   kCFCalendarUnitWeek = (1 << 8),
   kCFCalendarUnitWeekday = (1 << 9),
   kCFCalendarUnitWeekdayOrdinal = (1 << 10),
} CFCalendarUnit;

How do the (1 << 3) statements / variables work? I'm sorry if this is trivial, but could someone please enlighten me by either explaining or maybe posting a link to a good explanation?

Thanks!

-- ry

+1  A: 

The number 1 is represented as 00000000000000000000000000000001 (1 << n) means shift the 1 in 1's representation n places to the left So (1 << 3) would be 00000000000000000000000000001000 In one int you can have 32 options each of which can be turned on or off. Option number n is on if the n'th bit is 1

Itay
+2  A: 

If you look at a number in binary, each digit is either on (1) or off (0).

You can use bitwise operators to set or interrogate the individual bits efficiently to see if they are set or not.

Take the 8 bit value 156. In binary this is 10011100.

The set bits correspond to bits 7,4,3, and 2 (values 128, 16, 8, 4). You can compute these values with "1 << (position)" rather easily. So, 1 << 7 = 128.

Joe
A: 

1 << y is basically the same thing as 2 to the power of y

More generally, x << y is the same thing as x multiplied by 2 to the power of y.

In binary x << y means moving all the bits of x to the left by y places, adding zeroes in the place of the moved bits:

00010 << 2 = 01000

So:

1 << 1 = 2
1 << 2 = 4
1 << 3 = 8
...
IVlad
+4  A: 

Basically, the constants are represented just by one bit, so if you have a 32 bit integer, you can fit 32 constants in it. Your constants have to be powers of two, so they take only one "set" bit to represent.

For example:

#define CONSTANT_1 0x01 // 0001 in binary
#define CONSTANT_2 0x02 // 0010 in binary
#define CONSTANT_3 0x04 // 0100 in binary

then you can do

int options = CONSTANT_1 | CONSTANT_2; // will have 0101 in binary.

As you can see, each bit represents that particular constant. So you can binary AND in your code and test for the presence of each constant, like:

if (options & CONSTANT_2)
{
    // CONSTANT_2 is set
}

I recommend you to read about binary operations (they work like LOGICAL operators, but at the bit level), if you grok this stuff, it will make you a bit better of a programmer.

Cheers.

Francisco Soto
A: 

<< is the shift left operator, it shifts the bits of the first operand left by the number of positions specified in the right operand (with zeros coming into the shifted positions from the right).

In your enum you end up with values that eacg have a different bit set to 1, so when you construct something like unitDate, you can later find out which flags it contains by using the & operator, e.g. unitDate & NSMonthCalendarUnit == NSMonthCalendarUnit will be true.

Alex - Aotea Studios