26 Stimmen

Wie funktionieren diese Bitmasken eigentlich?

Diese Methode von NSCalendar nimmt zum Beispiel eine Bitmaske:

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

Optionen können also sein:

NSUInteger options = kCFCalendarUnitYear;

oder wie:

NSUInteger options = kCFCalendarUnitYear | kCFCalendarUnitMonth | kCFCalendarUnitDay;

Was ich nicht verstehe, ist, wie wird das eigentlich gemacht? Ich meine: Wie können sie die Werte herausziehen, die in options ? Wenn ich so etwas programmieren wollte, das eine Bitmaske verarbeiten kann, wie würde das aussehen?

36voto

Justin Niessner Punkte 235353

Bitmasken sind eigentlich ziemlich einfach. Sie können es sich so vorstellen (C#, bis jemand konvertieren kann):

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

Sie können dann die bitweisen Operatoren verwenden, um die Werte zu kombinieren:

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

Diese Technik wird auch häufig in Sicherheitsroutinen verwendet:

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;

Um dann die Sicherheitsstufe zu überprüfen, können Sie die bitweise und verwenden, um festzustellen, ob Sie über ausreichende Berechtigungen verfügen:

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

32voto

John Rasch Punkte 60054

Dazu müssen Sie den zu testenden Wert mit der Maske bitweise UND-verknüpfen und dann prüfen, ob das Ergebnis der UND-Verknüpfung mit der Maske übereinstimmt:

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

16voto

davidtbernal Punkte 13013

Bitmasken funktionieren, weil im Binärsystem jede Potenz von 2 (d.h. 2 0 \=1, 2 1 \=2, 2 1 \=4) einen einzigen Platz in der Bitfolge einnimmt. Zum Beispiel:

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

Wenn Sie or (der Betreiber | in C-ähnlichen Sprachen) zwei Zahlen a y b zusammen zu c Sie sagen also: "Nimm die Teile, die in a , b oder beides und setzen Sie sie in c ." Da eine Zweierpotenz eine einzelne Position in einer binären Zeichenfolge darstellt, gibt es keine Überschneidungen, und Sie können feststellen, welche Stellen gesetzt wurden. Zum Beispiel, wenn wir or 2 und 4

0010 | 0100 = 0110

Beachten Sie, dass sie im Grunde beides kombiniert. Andererseits, wenn wir or 5 und 3:

decimal | binary 
5       | 0101
3       | 0011

0101 | 0011 = 0111

Beachten Sie, dass wir nicht feststellen können, welche Bits woher stammen, da sich die binäre Darstellung der einzelnen Bits überschneidet.

Dies wird anhand eines weiteren Beispiels noch deutlicher. Nehmen wir die Zahlen 1, 2 und 4 (alles Potenzen von zwei)

0001 | 0010 | 0100 = 0111

Dies ist das gleiche Ergebnis wie 5 | 3 ! Da die ursprünglichen Zahlen jedoch Zweierpotenzen sind, können wir eindeutig feststellen, woher jedes Bit stammt.

6voto

Michael Patterson Punkte 1730

Der Schlüssel liegt darin, sich daran zu erinnern, dass jeder dieser Werte, die Sie in "Optionen" zusammenfassen, eigentlich nur eine Zahl ist. Ich bin mir nicht sicher, wie vertraut Sie mit dem Binärsystem sind, aber Sie können es sich auch als Dezimalzahl vorstellen und einfach Zahlen addieren, anstatt sie zu verrechnen.

Nehmen wir an, A=10, B=100 und C=1000

Wenn Sie Optionen = A+B einstellen wollten, dann wären die Optionen gleich 110. Die von Ihnen aufgerufene Methode würde dann die "Zehnerstelle" für A, die "Hunderterstelle" für B und die "Tausenderstelle" für C betrachten. In diesem Beispiel gibt es eine 1 an der Hunderterstelle und an der Zehnerstelle, so dass die Methode wüsste, dass A und B in den Optionen gesetzt wurden.

Es ist ein wenig anders, da Computer binär und nicht dezimal arbeiten, aber ich denke, die Idee ist sehr ähnlich, und manchmal ist es einfacher, darüber in einem vertrauten Zahlensystem nachzudenken.

2voto

Ramesh Punkte 1623
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)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X