2011-01-10 5 views
32

Vous êtes probablement familier avec le système enum de bitmask, comme:si (masque & VALUE) ou si ((masque & VALUE) == VALUE)?

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

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

f(FLAG2 | FLAG4); 

J'ai vu beaucoup de code qui teste ensuite pour un certain bit dans le masque comme

if ((mask & FLAG3) == FLAG3) 

Mais ISN n'est-ce pas équivalent?

if (mask & FLAG3) 

Y a-t-il une raison d'utiliser la première version? À mon avis, la deuxième version plus courte est plus lisible.

Peut-être des habitudes de restes des programmeurs C qui pensent que les vraies valeurs devraient être converties en 1? (Bien que même là, la version plus fait plus de sens dans une cession ou une déclaration return que dans un test de déclaration conditionnelle.)

+5

Faites-le maintenant avec le masque & ALL_FLAGS. Ce n'est plus la même chose. –

+4

'==' a une priorité supérieure à '&', vous avez donc besoin de parenthèses dans votre condition: 'if ((mask & FLAG3) == FLAG3)'. – casablanca

Répondre

75

La construction if ((mask & FLAG3) == FLAG3) teste si tous les bits dans FLAG3 sont présents dans le masque; if (mask & FLAG3) tests si sont sont présents. Si vous savez que FLAG3 a exactement 1 bit défini, ils sont équivalents, mais si vous définissez potentiellement des conditions composées, il peut être plus clair de prendre l'habitude de tester explicitement tous les bits, si c'est ce que vous voulez dire.

2

Quand il est un bitset, donc vous devez comparer un seul bit, il est d'accord pour avoir if(mask & value).

Mais, supposons que vous avez une adresse IP stockée sur fourmi int32 et vous voulez savoir s'il est 192.168.*, alors vous devrez faire:

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

if prend une valeur booléenne (bool). La première expression est directement de type bool, tandis que la dernière est une valeur numérique qui sera implicitement convertie en bool.

1

Votre condition sera vraie si le résultat est différent de zéro. Dans votre exemple, le résultat des deux opérations serait équivalent, et la deuxième option pourrait même être légèrement plus rapide car certains processeurs peuvent tester zéro plus facilement que d'autres nombres arbitraires, MAIS:

Évidemment, vous ne pouvez pas faire la seconde option si la valeur que vous vérifiez est constituée de plusieurs bits. Dans ce cas, vous devez utiliser la première option. Cela s'applique évidemment aussi si vous vérifiez plusieurs bits en même temps.

2

Même pour la valeur à un seul bit où ces instructions sont réellement équivalentes, je privilégie toujours la comparaison explicite.

  1. Cela rend l'intention plus claire. Nous vraiment sommes intéressés à comparer les drapeaux. (x & Flag) == Flag est un modèle établi et je peux le traiter et le reconnaître en un clin d'œil. En général, je préfère les conversions explicites plutôt que les conversions implicites. Je fais une exception pour les états d'échec (par ex.J'écris if (file) au lieu de if (file.good())) mais quand on travaille avec des nombres, 0 n'est pas un "état d'échec", c'est un nombre comme tous les autres. Je n'aime pas le traiter différemment dans un contexte booléen.

+0

Votre code au point (1) est incorrect. En raison de la priorité des opérateurs en C et C++, vous devez ajouter des parenthèses pour obtenir l'effet voulu. Un gotcha commun. – ChrisN