Подтвердить что ты не робот

Как эти битмаски действительно работают?

Например, этот метод из NSCalendar принимает битмаску:

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

Таким образом, параметры могут быть такими:

NSUInteger options = kCFCalendarUnitYear;

или как:

NSUInteger options = kCFCalendarUnitYear | kCFCalendarUnitMonth | kCFCalendarUnitDay;

То, что я не понимаю, как это делается? Я имею в виду: как они могут вытащить те значения, которые объединены в options? Если бы я хотел запрограммировать что-то вроде этого, это может принять битмаску, как бы это выглядело?

4b9b3361

Ответ 1

Чтобы сделать это, вы хотите поразрядное И значение, которое вы тестируете против маски, а затем посмотрите, равен ли результат ANDing самой маске:

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

Ответ 2

Битмаски на самом деле довольно простые. Вы можете думать об этом так (С#, пока кто-то не сможет конвертировать):

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

Ответ 3

Битмаксы работают, потому что в двоичной форме каждая степень 2 (т.е. 2 0= 1, 2 1= 2, 2 1= 4) занимает одно место в последовательности бит. Например:

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

Когда вы or (оператор | в C-подобных языках) два числа a и b вместе в c, вы говорите: "Возьмите биты, которые находятся в a, b, или оба, и поместите их в c." Поскольку степень двух символов представляет собой одну позицию в двоичной строке, нет совпадений, и вы можете определить, какие из них были установлены. Например, если мы or 2 и 4

0010 | 0100 = 0110

Обратите внимание, как это в основном объединяло два. С другой стороны, если мы or 5 и 3:

decimal | binary 
5       | 0101
3       | 0011

0101 | 0011 = 0111

обратите внимание, что мы не можем сказать, какие биты пришли откуда, потому что между двоичным представлением каждого из них было перекрытие.

Это становится более очевидным с еще одним примером. Возьмем числа 1, 2 и 4 (все степени два)

0001 | 0010 | 0100 = 0111

Это тот же результат, что и 5 | 3! Но так как исходные числа являются степенями двух, мы можем однозначно указать, откуда взялся каждый бит.

Ответ 4

Ключ помнит, что каждое из этих значений, которые вы объединяете в "параметры", действительно просто число. Я не уверен, насколько вы знакомы с бинарными, но вы можете думать об этом в десятичной форме и просто добавлять числа, а не их ORING.

Скажем, A = 10, B = 100 и C = 1000

Если вы хотите установить опции = A + B, то параметры будут равны 110. Затем метод, который вы назвали, будет смотреть на "десятки" места для A, "сотни" место для B и "тысячи" место для C. В этом примере есть 1 - это место в сотни и десятки, поэтому метод должен знать, что A и B заданы в параметрах.

Это немного отличается, поскольку компьютеры используют двоичный код не десятичный, но я думаю, что идея очень похожа, а иногда проще думать об этом в знакомой системе нумерации.

Ответ 5

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)

Ответ 6

Я нашел Calculator.app полезным в визуализации бит-масок. (Просто выберите "Вид" > "Программист", а затем нажмите кнопку "Показать двоичный файл" ). (Вы можете щелкнуть по любой из 0 или 1 в бинарной таблице, чтобы включить или выключить эти биты, или ввести числа в десятичном или шестнадцатеричном формате (используйте переключатель 8 | 10 | 16 NSSegmentedControl для переключения между различными представлениями)).