1

我不是 C/C++ 方面的专家。

我今天发现了这个声明:

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

你们能翻译每个值将具有的值吗?

4

4 回答 4

6

运算符<<按位左移运算符。将所有位左移指定次数:(算术左移并保留符号位)

m << n

将 的所有位m向左移动n多次。(注意一班 == 乘以二)。

1 << 0表示没有移位,因此它等于1only。

1 << 1表示一个班次,因此它仅等于1*2= 2。

我用一个字节解释:一个字节是这样的:

 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

1 << 0除了图一之外什么也不做。(注意第 7 位被复制以保留符号)

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  

|是位操作符。在下面的代码中它or 1 | 2==3

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

没有更多的技术原因来初始化这样的值,这样定义会使事情很好地排列起来阅读这个答案:define SOMETHING (1 << 0)

编译器优化将它们转换为更简单的:(我不确定第三个,但我认为编译器也会优化它

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

编辑: @感谢直到。阅读此答案带有 BOOL 标志的 App States显示了使用位运算符获得的声明的有用性。

于 2013-03-29T17:45:54.887 回答
3

这是位标志的枚举:

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

进而

PKRevealControllerTypeBoth = 
  (PKRevealControllerTypeLeft | PKRevealControllerTypeRight)

只是对其他两个标志进行按位或运算的结果。因此,设置了位 0 和位 1。

运算符是<<左移运算符。并且|运算符是按位或。

总之,结果值为:

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

但是从位标志的角度来考虑它会更有意义。或者作为通用集的集合:{ PKRevealControllerTypeLeft, PKRevealControllerTypeRight }

要了解更多信息,您需要阅读有关枚举、移位运算符和位运算符的信息。

于 2013-03-29T17:44:51.733 回答
2

这一切都归结为按位算术。

PKRevealControllerTypeNone 的值为 0(二进制 0000)

PKRevealControllerTypeLeft 的值为 1(二进制 0001)

PKRevealControllerTypeRight 的值为 2(二进制 0010),因为 0001 左移 1 位是 0010

PKRevealControllerTypeBoth 自 0010 以来的值为 3(二进制 0011)| 0001(或类似加法)= 0011

在上下文中,这最有可能用于确定值。属性 is &(or bitwise-and) 的作用类似于乘法。如果1ands 有一个数字,那么这个数字会被保留,如果0ands 有一个数字,那么这个数字就会被清除。

因此,如果你想检查一个特定的控制器是否是特定类型Left的并且它的值0010(即 type Right0010 & 0001 = 0正如我们所期望的那样是 false (因此,你已经确定它不是正确的类型)。但是,如果控制器是Both 0011 & 0001 = 1这样,结果是正确的,因为我们确定这是Both类型。

于 2013-03-29T17:45:05.077 回答
2

这看起来像 Objective C 而不是 C++,但无论如何:

1 << 0

只是左移(上)0 个位置。任何整数“<<0”都是它自己。

所以

1 << 0 = 1

相似地

1 << 1

只是左移一位。您可以通过多种方式可视化,但最简单的方法是乘以 2。[注 1]

所以

x << 1 == x*2

或者

1 << 1 == 2

最后,单管道运算符是按位或

所以

1 | 2 = 3

tl;博士:

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

[1] 这种泛化存在一些限制,例如,当x等于或大于数据类型能够存储的最大值的 1/2 时。

于 2013-03-29T17:47:48.793 回答