2011-01-10 19 views
32

Jesteś prawdopodobnie zna programu enum bitową, jak:jeśli (maska ​​i WARTOŚĆ) lub jeśli ((maska ​​i WARTOŚĆ) == WARTOŚĆ)?

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

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

f(FLAG2 | FLAG4); 

Widziałem dużo kodu, który następnie testy dla określonego bitu w masce jak

if ((mask & FLAG3) == FLAG3) 

Ale ISN to odpowiednik tego?

if (mask & FLAG3) 

Czy istnieje jakiś powód, aby korzystać z pierwszej wersji? Moim zdaniem druga, krótsza wersja jest bardziej czytelna.

Może resztki nawyków od programistów C, którzy myślą, że prawdziwe wartości powinny zostać przekonwertowane na 1? (Chociaż nawet tam, dłuższa wersja ma większy sens w cesji lub return oświadczenie niż w warunkowej badania sprawozdania).

+5

Teraz zrób to z maską i ALL_FLAGS. Nie ma już tego samego. –

+4

'==' ma wyższy priorytet niż 'i', więc potrzebujesz nawiasów w swoim stanie: 'if ((maska ​​i FLAG3) == FLAG3)'. – casablanca

Odpowiedz

75

Konstrukt if ((mask & FLAG3) == FLAG3) sprawdza, czy bity w FLAG3 są obecne w masce; if (mask & FLAG3) testów, jeśli są obecne dowolne.

Jeśli wiesz, że FLAG3 ma dokładnie 1 bitowy zestaw, są one równoważne, ale jeśli potencjalnie definiujesz złożone warunki, możesz być bardziej przejrzystym, aby nabrać nawyku jawnego testowania wszystkich bitów, jeśli o to ci chodzi.

2

Gdy jest za bitset, więc trzeba porównać tylko pojedynczy trochę, to jest dobrze mieć if(mask & value).

Ale załóżmy, że masz adres IP zapisany na mrówki int32 i chcesz wiedzieć czy jest 192.168.*, następnie trzeba będzie zrobić:

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

if przyjmuje wartość logiczną (bool). Pierwsze wyrażenie jest bezpośrednio typu bool, natomiast drugie jest wartością numeryczną, która zostanie niejawnie przekształcona na bool.

1

Twój stan będzie prawdziwy, jeśli wynik będzie niezerowy. W twoim przykładzie wynik obu operacji byłby równoważny, a druga opcja mogłaby być nieco szybsza, ponieważ niektóre procesory mogą testować na zero łatwiej niż inne dowolne numery, ALE:

Oczywiście, nie możesz zrobić drugiego opcja, jeśli sprawdzana wartość składa się z więcej niż jednego bitu. W takim przypadku musisz użyć pierwszej opcji. To oczywiście odnosi się również do sprawdzania kilku bitów w tym samym czasie.

2

Nawet w przypadku wartości jednobitowej, w której te stwierdzenia są rzeczywiście równoważne, zawsze preferuję jednoznaczne porównanie.

  1. Dzięki temu cel jest wyraźniejszy. Naprawdę interesuje nas porównywanie flag. (x & Flag) == Flag to ustalony wzór i mogę go przetwarzać i rozpoznawać w mgnieniu oka.

  2. Zwykle preferuję jawne konwersje niejawne. Robię wyjątek dla stanów fail (np.Piszę if (file) zamiast if (file.good())), ale podczas pracy z liczbami 0 nie jest "stanem awaryjnym", jest to liczba jak każda inna. Nie lubię traktować tego inaczej w kontekście boolowskim.

+0

Twój kod w pkt (1) jest nieprawidłowy. Ze względu na pierwszeństwo operatorów w C i C++, musisz dodać nawiasy, aby uzyskać zamierzony efekt. Typowy grosz. – ChrisN

Powiązane problemy