这些位掩码实际上如何工作?

时间:2010-03-31 17:31:57

标签: iphone objective-c cocoa cocoa-touch

例如,NSCalendar中的此方法采用位掩码:

- (NSDate *)dateByAddingComponents:(NSDateComponents *)comps toDate:(NSDate *)date options:(NSUInteger)opts

所以选项可以是:

NSUInteger options = kCFCalendarUnitYear;

或者喜欢:

NSUInteger options = kCFCalendarUnitYear | kCFCalendarUnitMonth | kCFCalendarUnitDay;

我没有得到的是,这实际上是怎么做到的?我的意思是:他们怎样才能提取合并到options的那些值?如果我想编写这样的东西,那可能需要一个位掩码,那看起来怎么样?

6 个答案:

答案 0 :(得分:36)

Bitmasks非常基本。你可以这样想(C#直到有人可以转换):

public enum CalendarUnits
{
    kCFCalendarUnitDay = 1, // 001 in binary
    kCFCalendarUnitMonth = 2, // 010 in binary
    kCFCalendarUnitYear = 4, // 100 in binary
}

然后,您可以使用按位运算符组合值:

// The following code will do the following
// 001 or 100 = 101
// So the value of options should be 5
NSUInteger options = kCFCalendarUnitDay | kCFCalendarUnitYear;

此技术也经常用于安全例程:

public enum Priveledges
{
    User = 1,
    SuperUser = 2,
    Admin = 4
}

// SuperUsers and Admins can Modify
// So this is set to 6 (110 binary)
public int modifySecurityLevel = SuperUser | Admin;

然后要检查安全级别,您可以使用按位并查看您是否有足够的权限:

public int userLevel = 1;
public int adminLevel = 4;

// 001 and 110 = 000 so this user doesn't have security
if(modifySecurityLevel & userLevel == userLevel)

// but 100 and 110 = 100 so this user does
if(modifySecurityLevel & adminLevel == adminLevel)
    // Allow the action

答案 1 :(得分:32)

要执行此操作,您希望按位AND对正在测试的掩码进行测试,然后查看ANDing的结果是否等于掩码本身:

if ((options & kCFCalendarUnitYear) == kCFCalendarUnitYear) {
   // do whatever
}

答案 2 :(得分:16)

Bitmasks有效,因为在二进制中,每个幂为2(即2 0 = 1,2 1 = 2,2 1 = 4)在比特序列中占据一个点。例如:

decimal | binary 
1       | 0001
2       | 0010
4       | 0100
8       | 1000

当您or(C语言中的运算符|)将ab两个数字合并为c时,您说“取ab或两者中的位并将它们放入c。“由于2的幂表示二进制字符串中的单个位置,因此没有重叠,您可以确定设置了哪些。例如,如果我们or 2和4

0010 | 0100 = 0110

注意它基本上是如何组合这两者的。另一方面,如果我们or 5和3:

decimal | binary 
5       | 0101
3       | 0011

0101 | 0011 = 0111

请注意,我们无法确定哪些位来自哪里,因为每个位的二进制表示之间存在重叠。

再一个例子,这一点变得更加明显。我们取数字1,2和4(所有2的幂)

0001 | 0010 | 0100 = 0111

这与5 | 3的结果相同!但由于原始数字是2的幂,我们可以唯一地说出每个位的来源。

答案 3 :(得分:6)

关键是要记住,您合并到“选项”中的每个值实际上只是一个数字。我不确定你对二进制文件有多熟悉,但你可以用十进制来考虑它而只是添加数字而不是对它们进行OR运算。

假设A = 10,B = 100,C = 1000

如果你想设置options = A + B,那么选项将等于110.你调用的方法将查看A的“十”位置,B的“数百”位置和“千位”位置对于C.在这个例子中,有一个是数百位和十位,所以该方法会知道A和B是在选项中设置的。

由于计算机使用二进制而非十进制,这有点不同,但我认为这个想法非常相似,有时在熟悉的编号系统中更容易思考。

答案 4 :(得分:3)

typedef NS_OPTIONS(NSUInteger, MyOption)
{
   OptionNone = 0,
   OptionOne = 1 << 0,
   OptionTwo = 1 << 1,
   OptionThree = 1 << 2
};

if (givenValue & OptionOne) {
   // bit one is selected
}

if (givenValue & OptionTwo) {
   // bit two is selected
}

http://en.wikipedia.org/wiki/Mask_(computing)

答案 5 :(得分:0)

我发现Calculator.app有助于可视化位掩码。 (只需选择View&gt; Programmer,然后单击按钮显示二进制)。 (您可以单击二进制表中的任何0或1来打开或关闭这些位;或者,输入十进制或十六进制的数字(使用8 | 10 | 16 NSSegmentedControl在不同的表示之间切换)。)