1

I am not a specialist in C/C++.

I found this declaration today:

typedef NS_OPTIONS(NSUInteger, PKRevealControllerType)
{
    PKRevealControllerTypeNone  = 0,
    PKRevealControllerTypeLeft  = 1 << 0,
    PKRevealControllerTypeRight = 1 << 1,
    PKRevealControllerTypeBoth = (PKRevealControllerTypeLeft | PKRevealControllerTypeRight)
};

Can you guys translate what values every value will have?

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
Duck
  • 34,902
  • 47
  • 248
  • 470
  • 1
    Looks like Objective C, not C++ – jedwards Mar 29 '13 at 17:42
  • Which language? There's no such language as C/C++, and this looks like a different language still. And what about that macro? What is `NS_OPTIONS`? – David Heffernan Mar 29 '13 at 17:42
  • forget that. I would like to know what values every of the 3 other values will have. What 1 << 0, 1 << 1 and the third one will produce? – Duck Mar 29 '13 at 17:44
  • @David: `NS_OPTIONS` is an Objective-C specific macro; see [this question](http://stackoverflow.com/questions/14080750/objective-c-enumeration-ns-enum-ns-options). But apparently that's not what the OP is asking about. – Keith Thompson Mar 29 '13 at 17:46
  • they will be 0, 1, 2, 3. But the writer wanted to make it clear that they were mutually compatible flags not just numbers. `1<<0` means 1 leftshifted by 0 bits, so 1. `1<<1` means left-shift by 1, so it becomes 2. Then `1|2` (what the last line effectively is) is 3. – Dave Mar 29 '13 at 17:47
  • This is in obj-C. But the OP wanted to know about `<<` which is from X and C++. so nothing to do with obj-C for understanding the meaning od `ShiftOperator` – Anoop Vaidya Mar 29 '13 at 17:50
  • 2
    what's wrong with **reading the documentation** – Cheers and hth. - Alf Mar 29 '13 at 18:11

4 Answers4

6

opertor << is bitwise left shift operator. Shift all the bits to left a specified number of times: (arithmetic left shift and reserves sign bit)

m << n

Shift all the bits of m to left a n number of times. (notice one shift == multiply by two).

1 << 0 means no shift so its equals to 1 only.

1 << 1 means one shift so its equals to 1*2 = 2 only.

I explain with one byte: one in one byte is like:

 MSB
+----+----+----+---+---+---+---+---+
|  0 |  0 | 0  | 0 | 0 | 0 | 0 | 1 |       1   
+----+----+----+---+---+---+---+---+
  7     6   5    4   3   2   1 / 0  
  |                           /           1 << 1
  |                          | 
  ▼                          ▼
+----+----+----+---+---+---+---+---+
|  0 |  0 | 0  | 0 | 0 | 0 | 1 | 0 |       2      
+----+----+----+---+---+---+---+---+ 
   7    6   5    4   3   2   1   0

Whereas 1 << 0 do nothing but its like figure one. (notice 7th bit is copied to preserve sign)

OR operator: do bit wise or

 MSB                            PKRevealControllerTypeLeft
+----+----+----+---+---+---+---+---+
|  0 |  0 | 0  | 0 | 0 | 0 | 0 | 1 |  == 1
+----+----+----+---+---+---+---+---+
   7    6   5    4   3   2   1   0
   |    |    |   |   |   |   |   |      OR
 MSB                               PKRevealControllerTypeRight
+----+----+----+---+---+---+---+---+
|  0 |  0 | 0  | 0 | 0 | 0 | 1 | 0 |   == 2
+----+----+----+---+---+---+---+---+
   7    6   5    4   3   2   1   0

 = 

 MSB                    PKRevealControllerTypeBoth
+----+----+----+---+---+---+---+---+
|  0 |  0 | 0  | 0 | 0 | 0 | 1 | 1 |   == 3
+----+----+----+---+---+---+---+---+
   7    6   5    4   3   2   1   0  

| is bit wise operator. in below code it or 1 | 2 == 3

PKRevealControllerTypeNone  = 0,             //  is Zero
PKRevealControllerTypeLeft  = 1 << 0,        //  one 
PKRevealControllerTypeRight = 1 << 1,        //  two
PKRevealControllerTypeBoth = (PKRevealControllerTypeLeft |    
                             PKRevealControllerTypeRight)  // three

There is not more technical reason to initialized values like this, defining like that makes things line up nicely read this answer:define SOMETHING (1 << 0)

compiler optimization convert them in simpler for like: (I am not sure for third one, but i think compiler will optimize that too)

PKRevealControllerTypeNone  = 0,     //  is Zero
PKRevealControllerTypeLeft  = 1,     //  one 
PKRevealControllerTypeRight = 2,     //  two
PKRevealControllerTypeBoth  = 3,     // Three

Edit: @thanks to Till. read this answer App States with BOOL flags show the usefulness of declarations you got using bit wise operators.

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • wasn't easier to set it like 0, 1, 2, 3? Is there any reason to be insane like this? – Duck Mar 29 '13 at 17:49
  • It makes it clear that it is a set of bit flags – David Heffernan Mar 29 '13 at 17:51
  • @DesperateDeveloper I don't think I believe programmer doing like this to make his this part of code uniformly same with other part of code – Grijesh Chauhan Mar 29 '13 at 17:54
  • @DesperateDeveloper What you asking to me similar thing is asked here in [this question](http://stackoverflow.com/questions/15095350/define-something-1-0) here you find better answer – Grijesh Chauhan Mar 29 '13 at 17:57
  • @DavidHeffernan ok you mean its arithmetic left shift. correct? – Grijesh Chauhan Mar 29 '13 at 18:07
  • 1
    +1 ASCII art for the win! – David Heffernan Mar 29 '13 at 18:11
  • @DavidHeffernan thanks :D :D ..I always answer this way yes. – Grijesh Chauhan Mar 29 '13 at 18:13
  • 1
    @DesperateDeveloper for a good reasoning on why people use such complicated looking expressions, you may want to check questions/answers like http://stackoverflow.com/a/8956606/91282 – Till Mar 29 '13 at 18:41
  • @Desperate Developer please check the link Till posted http://stackoverflow.com/questions/8956364/app-states-with-bool-flags?answertab=votes#tab-top – Grijesh Chauhan Mar 29 '13 at 18:45
  • +1 - As an aside, I think the 0,1,2,3 syntax is horrible (I know you gave it as a logical equivalence, but I don't want people to read it as an endorsement). I know that for users not accustomed to bitwise operations, the more explicit shifting syntax looks awkward, but once you get used to it, the presences of bitwise shift operators makes it clear to future developers that you can use bitwise and (`&`) operations and the like. If you use 0,1,2,3, it would be unwise to make that sort of assumption. – Rob Mar 29 '13 at 20:15
  • @Rob yes agree. initialized with 0,1,2,3 is like hard coded. whereas using bitwise is programmatically. i think. – Grijesh Chauhan Mar 30 '13 at 02:18
  • @DavidHeffernan you may also [like to draw ascii image](http://www.asciiflow.com/#Draw) – Grijesh Chauhan Apr 09 '13 at 12:23
3

It's an enum of bit flags:

PKRevealControllerTypeNone  = 0       // no flags set
PKRevealControllerTypeLeft  = 1 << 0, // bit 0 set
PKRevealControllerTypeRight = 1 << 1, // bit 1 set

And then

PKRevealControllerTypeBoth = 
  (PKRevealControllerTypeLeft | PKRevealControllerTypeRight)

is just the result of bitwise OR-ing the other two flags. So, bit 0 and bit 1 set.

The << operator is the left shift operator. And the | operator is bitwise OR.

In summary the resulting values are:

PKRevealControllerTypeNone  = 0
PKRevealControllerTypeLeft  = 1
PKRevealControllerTypeRight = 2
PKRevealControllerTypeBoth  = 3

But it makes a lot more sense to think about it in terms of flags of bits. Or as a set where the universal set is: { PKRevealControllerTypeLeft, PKRevealControllerTypeRight }

To learn more you need to read up about enums, shift operators and bitwise operators.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

This all comes down to bitwise arithmetic.

PKRevealControllerTypeNone has a value of 0 (binary 0000)

PKRevealControllerTypeLeft has a value of 1 (binary 0001)

PKRevealControllerTypeRight has a value of 2 (binary 0010) since 0001 shifted left 1 bit is 0010

PKRevealControllerTypeBoth has a value of 3 (binary 0011) since 0010 | 0001 (or works like addition) = 0011

In context, this is most-likely used to determine a value. The property is & (or bitwise-and) works similar to multiplication. If 1 ands with a number, then the number is preserved, if 0 ands with a number, then the number is cleared.

Thus, if you want to check if a particular controller is specifically type Left and it has a value of 0010 (i.e. type Right) 0010 & 0001 = 0 which is false as we expect (thus, you have determined it is not of correct type). However, if the controller is Both 0011 & 0001 = 1 so the result is true which is correct since we determined this is of Both types.

RageD
  • 6,693
  • 4
  • 30
  • 37
  • 0000, 0001, 0010, 0011... ? wasn't easier to set it like 0, 1, 2, 3? Is there any reason to be insane like this? – Duck Mar 29 '13 at 17:47
  • I have added more to my response - you can see how this is used in practice. – RageD Mar 29 '13 at 17:49
  • @DesperateDeveloper: Seeing a number like “2” doesn't tell you easily which bit(s) are set in that number. Left-shift expressions do. This becomes important if you print the value of a `PKRevealControllerType` variable and want to know what options are set in it; you can paste the number into Calculator, switch to programmer mode, and look at the bits display. – Peter Hosey Mar 30 '13 at 01:18
2

This looks like Objective C and not C++, but regardless:

1 << 0

is just one bitshifted left (up) by 0 positions. Any integer "<<0" is just itself.

So

1 << 0 = 1

Similarly

1 << 1

is just one bitshifted left by 1 position. Which you could visualize a number of ways but the easiest is to multiply by 2.[Note 1]

So

x << 1 == x*2

or

1 << 1 == 2

Lastly the single pipe operator is a bitwise or.

So

1 | 2 = 3

tl;dr:

PKRevealControllerTypeNone  = 0
PKRevealControllerTypeLeft  = 1
PKRevealControllerTypeRight = 2
PKRevealControllerTypeBoth  = 3

[1] There are some limitations on this generalization, for example when x is equal to or greater than 1/2 the largest value capable of being stored by the datatype.

jedwards
  • 29,432
  • 3
  • 65
  • 92
  • wasn't easier to set it like 0, 1, 2, 3? Is there any reason to be insane like this? – Duck Mar 29 '13 at 17:49
  • @DesperateDeveloper the values are flags not numbers. This setup makes it obvious that each flag is independent, and the last is a combination of the other two. If you had 20 flags, the "normal" numbers would get difficult to manage; what does 65544 do? In this form, I would know that it is `(1<<16) | (1<<3)`, which means it represents 2 flags. Just learn bitshift operators and it's no-longer "insane". – Dave Mar 29 '13 at 17:53
  • Well, it compiles to the same code, so the only difference is how it's expressed in the source. I think this approach is probably better than 0,1,2,3. Three things make it look odd though, [1] That they defined a separate value for "None" (0). This isn't done all that often. [2] That they defined a separate variable for (1|2). Usually this isn't done either. Usually the decimal values of the flags increase by powers of 2 -- 1,2,4,8,16,etc. And [3], there are only 2 bits used in the bitfield. Often there are much more. – jedwards Mar 29 '13 at 17:54
  • @jedwards I always define a 0 value, because (in C++) it's not happy if you just send the (int) 0 when you want no flags, and you can't always rely on default values. Combining flags is also pretty common, as is aliasing, because it makes the code which uses the function more readable. Also having such a short bitfield isn't so unusual either! In fact, the standard cocoa library has many examples which are (almost) this short. – Dave Mar 29 '13 at 17:57
  • @Dave, thanks for the insight. I'm not an ObjC developer myself, so the note about the cocoa libraries is interesting. If I alias, I'll usually do it in a separate place, but I guess they did that here -- the length is misleading. As for defining a 0, that makes a lot of sense -- my C background got the best of me :-) – jedwards Mar 29 '13 at 18:06