2011-01-10 42 views
32

Bạn đang có lẽ quen thuộc với chương trình enum bitmask, như:nếu (mặt nạ & VALUE) hoặc nếu ((mặt nạ & VALUE) == VALUE)?

enum Flags { 
    FLAG1 = 0x1, 
    FLAG2 = 0x2, 
    FLAG3 = 0x4, 
    FLAG4 = 0x8, 

    NO_FLAGS = 0, 
    ALL_FLAGS = FLAG1 | FLAG2 | FLAG3 | FLAG4 
}; 

f(FLAG2 | FLAG4); 

Tôi đã nhìn thấy rất nhiều mã mà sau đó thử nghiệm cho một chút nào đó trong mặt nạ như

if ((mask & FLAG3) == FLAG3) 

Nhưng isn Điều đó tương đương với điều này?

if (mask & FLAG3) 

Có lý do nào để sử dụng phiên bản đầu tiên không? Theo tôi, phiên bản ngắn hơn thứ hai dễ đọc hơn.

Có thể các thói quen còn sót lại từ các lập trình viên C nghĩ rằng giá trị thực cần được chuyển đổi thành 1? (Mặc dù ngay cả ở đó, phiên bản dài hơn có ý nghĩa hơn trong một bài tập hoặc tuyên bố return hơn là trong bài kiểm tra tuyên bố có điều kiện.)

+5

Làm ngay với mặt nạ & ALL_FLAGS. Không còn giống nhau nữa. –

+4

'==' có ưu tiên cao hơn '&', vì vậy bạn cần dấu ngoặc đơn trong điều kiện của bạn: 'if ((mask & FLAG3) == FLAG3)'. – casablanca

Trả lời

75

Cấu trúc if ((mask & FLAG3) == FLAG3) kiểm tra nếu tất cả bit trong FLAG3 đều có trong mặt nạ; if (mask & FLAG3) kiểm tra nếu có bất kỳ nào có mặt. Nếu bạn biết FLAG3 có chính xác 1 bit, chúng tương đương nhau, nhưng nếu bạn có khả năng xác định các điều kiện hỗn hợp, nó có thể rõ ràng hơn để có thói quen kiểm tra rõ ràng cho tất cả các bit, nếu đó là ý của bạn.

2

Khi nó là bitet, vì vậy bạn phải so sánh chỉ đơn bit, được phép có if(mask & value).

Nhưng, giả sử rằng bạn có một địa chỉ IP được lưu trữ trên kiến ​​int32 và bạn muốn biết cho dù đó là 192.168.*, sau đó bạn sẽ phải làm:

if((ip & 0xFFFF0000) == 0xC0A80000) // assuming some endianness representation. 
1

if mất một boolean (bool). Biểu thức trước đây là trực tiếp thuộc loại bool, trong khi biểu thức sau là giá trị số sẽ được chuyển đổi hoàn toàn thành bool.

1

Điều kiện của bạn sẽ đúng nếu kết quả không khác. Trong ví dụ của bạn, kết quả của cả hai thao tác sẽ là tương đương và tùy chọn thứ hai thậm chí có thể nhanh hơn một chút vì một số CPU có thể kiểm tra không dễ dàng hơn các số tùy ý khác, NHƯNG:

Rõ ràng là bạn không thể làm thứ hai nếu giá trị bạn đang kiểm tra bao gồm nhiều hơn một bit. Trong trường hợp đó, bạn phải sử dụng tùy chọn đầu tiên. Điều đó rõ ràng cũng được áp dụng nếu bạn đang kiểm tra nhiều bit cùng một lúc.

2

Ngay cả đối với giá trị bit đơn nơi các câu lệnh này thực sự tương đương, tôi luôn ưu tiên so sánh rõ ràng.

  1. Nó làm cho mục đích rõ ràng hơn. Chúng tôi thực sự quan tâm đến việc so sánh cờ. (x & Flag) == Flag là một mẫu được thiết lập và tôi có thể xử lý và nhận ra nó trong chớp mắt.

  2. Tôi thường thích rõ ràng hơn về chuyển đổi tiềm ẩn. Tôi tạo ngoại lệ cho các trạng thái không thành công (ví dụ:Tôi viết if (file) thay vì if (file.good())) nhưng khi làm việc với số, 0 không phải là "trạng thái lỗi", nó giống như bất kỳ số nào khác. Tôi không thích xử lý nó một cách khác biệt trong một bối cảnh boolean.

+0

Mã của bạn tại điểm (1) không chính xác. Vì ưu tiên toán tử trong C và C++, bạn cần phải thêm dấu ngoặc đơn để có được hiệu ứng mong muốn. Một dấu hiệu phổ biến. – ChrisN