2010-03-31 44 views
26

Ví dụ, phương pháp này từ NSCalendar mất một bitmask:Các bitmap thực sự hoạt động như thế nào?

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

Vì vậy, tùy chọn có thể được như:

NSUInteger options = kCFCalendarUnitYear; 

hay như:

NSUInteger options = kCFCalendarUnitYear | kCFCalendarUnitMonth | kCFCalendarUnitDay; 

Những gì tôi không nhận được là , điều này thực sự được thực hiện như thế nào? Ý tôi là: Làm thế nào họ có thể rút ra những giá trị được hợp nhất thành options? Nếu tôi muốn lập trình một cái gì đó như thế này, có thể mất một chút, làm thế nào mà trông?

+0

làm thẻ như iPhone và khách quan-C thực sự giúp khi thông tin này là đúng (và thậm chí cả cú pháp là như nhau) trong nhiều ngôn ngữ? – speedfranklin

Trả lời

32

Để làm điều này, bạn muốn Bitwise và giá trị mà bạn đang thử nghiệm chống lại mặt nạ, sau đó xem nếu kết quả của ANDing bằng mặt nạ tự:

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

== kCFCalendarUnitYear có vẻ không cần thiết – sigjuice

+12

Thực tế, nếu (tùy chọn & kCFCalendarUnitYear) 'phải đủ bởi vì bất kỳ giá trị khác 0 sẽ có nghĩa là bit đã được đặt. – FRotthowe

+0

COOL man, COOL! – dontWatchMyProfile

36

Bitmasks là khá cơ bản thực sự. Bạn có thể nghĩ về nó như thế này (C# cho đến khi ai đó có thể chuyển đổi):

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

Sau đó bạn có thể sử dụng các toán tử Bitwise để kết hợp các giá trị:

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

Kỹ thuật này cũng thường được sử dụng trong thói quen an ninh :

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; 

Sau đó, để kiểm tra mức độ bảo mật, bạn có thể sử dụng các phép toán và để xem nếu bạn có đủ phép:

012.351.
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 
+2

Lưu ý rằng do ưu tiên toán tử, 'if (modifySecurityLevel & userLevel == userLevel)' phải là 'if ((modifySecurityLevel & userLevel) == userLevel)' nếu không thì biểu thức sẽ luôn luôn đánh giá là true. – Drahcir

+0

Bạn cũng có thể thực hiện thay đổi bit như sau: = 1 << 1; – Mark

6

Điều quan trọng là ghi nhớ rằng mỗi một trong những giá trị bạn hợp nhất thành "tùy chọn" thực sự chỉ là một số. Tôi không chắc bạn quen thuộc với nhị phân như thế nào, nhưng bạn có thể nghĩ về số thập phân và chỉ cần thêm số thay vì ORING chúng.

Hãy nói rằng A = 10, B = 100, và C = 1.000

Nếu bạn muốn thiết lập tùy chọn = A + B, sau đó tùy chọn sẽ bằng 110. Phương pháp bạn gọi sau đó sẽ xem xét các "hàng chục "vị trí cho A," hàng trăm "nơi cho B, và" hàng ngàn "nơi cho C. Trong ví dụ này, có 1 là hàng trăm nơi và hàng chục nơi, vì vậy phương pháp sẽ biết rằng A và B đã được thiết lập trong các tùy chọn.

Có một chút khác biệt vì máy tính sử dụng nhị phân không phải là số thập phân, nhưng tôi nghĩ ý tưởng này rất giống nhau và đôi khi dễ dàng nghĩ về nó trong một hệ thống đánh số quen thuộc.

+2

giải thích tốt! cảm ơn! – dontWatchMyProfile

+2

Ý tưởng không chỉ giống nhau, mà chính xác như nhau. Chỉ có cơ sở là khác nhau: 2 so với 10. Bất kỳ ai quen thuộc với dòng lệnh UNIX/Linux cũng đã thực hiện điều này trong cơ sở-8 (bát phân), vì đó là cách mặt nạ cấp phép số của lệnh chmod làm việc. –

16

Bitmasks làm việc vì ở dạng nhị phân, mỗi sức mạnh của 2 (ví dụ: 2 = 1, 2 = 2, 2 = 4) chiếm một vị trí duy nhất trong chuỗi các bit. Ví dụ:

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

Khi bạn or (các nhà điều hành | bằng các ngôn ngữ C-like) hai số ab với nhau thành c, bạn đang nói "lấy các bit có trong a, b, hoặc cả hai và đặt chúng trong c."Kể từ khi một sức mạnh của hai đại diện cho một vị trí duy nhất trong một chuỗi nhị phân, không có sự chồng chéo, và bạn có thể xác định những người đã được thiết lập. Ví dụ, nếu chúng ta or 2 và 4

0010 | 0100 = 0110 

Thông báo như thế nào về cơ bản kết hợp . hai Mặt khác, nếu chúng ta or 5 và 3:.

decimal | binary 
5  | 0101 
3  | 0011 

0101 | 0011 = 0111 

thông báo rằng chúng tôi không có cách nào kể mà bit đến từ đâu, vì đã có sự chồng chéo giữa các đại diện nhị phân của mỗi

Beco này mes rõ ràng hơn với một ví dụ nữa. Hãy lấy các số 1, 2 và 4 (tất cả các quyền của hai)

0001 | 0010 | 0100 = 0111 

Đây cũng là kết quả tương tự như 5 | 3! Nhưng vì những con số ban đầu là sức mạnh của hai, chúng ta có thể nói duy nhất từng bit xuất phát từ đâu.

+0

Ví dụ tuyệt vời nhưng tôi không hiểu câu cuối của bạn. Làm thế nào chúng ta có thể biết nếu 0111 đến từ 0001 | 0010 | 0100 HOẶC 0101 | 0011? – joels

+0

Toàn bộ vấn đề là chúng ta biết * một ưu tiên * rằng các cờ chỉ là sức mạnh của hai. Nói cách khác, chúng ta biết đó là '0001 | 0010 | 0100 | 'và không phải là' 0101 | 0011' bởi vì sau này không đơn giản là một lựa chọn, vì nó không chỉ bao gồm hai lũy thừa. – notJim

0

Tôi đã tìm thấy Calculator.app hữu ích trong việc hiển thị mặt nạ bit. (Chỉ cần chọn View> Programmer, và sau đó nhấp vào nút Show Binary). (Bạn có thể nhấp vào bất kỳ số 0 hoặc 1 trong bảng nhị phân để bật hoặc tắt các bit đó hoặc nhập các số thập phân hoặc hex (sử dụng 8 | 10 | 16 NSSegmentedControl để chuyển đổi giữa các biểu diễn khác nhau)).

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)

Các vấn đề liên quan