web-dev-qa-db-fra.com

Existe-t-il une différence entre && et & avec bool (s)?

En C++, existe-t-il une différence entre && (logique) et & (au niveau du bit) entre bool (s)?

bool val1 = foo();
bool val2 = bar();

bool case1 = val1 & val2;
bool case2 = val1 && val2;

case1 et case2 sont-ils identiques ou, sinon, comment varient-ils exactement et pourquoi l’un choisirait-il l’un sur l’autre? Est-ce qu'un bitwise et de bools est portable?

31
WilliamKF

Le standard garantit que false est converti en zéro et true est converti en un en tant qu'entiers:

4.7 Conversions intégrales

...

Si le type de destination est bool, voir 4.12. Si le type de source est bool, la valeur false est convertie en zéro et la valeur true en un.

Ainsi, dans l'exemple que vous donnez, l'effet est garanti identique et portable à 100%.

Dans le cas que vous donnez, tout compilateur décent est susceptible de générer un code identique (optimal).

Cependant, pour les expressions booléennes expr1 et expr2, il n'est pas vrai que expr1 && expr2 est identique à expr1 & expr2 car && effectue une évaluation "en court-circuit". Autrement dit, si expr1 est évalué à false, expr2 ne sera même pas évalué. Cela peut affecter les performances (si expr2 est compliqué) et le comportement (si expr2 a des effets secondaires). (Mais notez que la forme & peut en réalité être plus rapide si elle évite une branche conditionnelle ... Jouer avec ce genre de chose pour des raisons de performance est presque toujours une mauvaise idée.)

Ainsi, pour l'exemple spécifique que vous donnez, où vous chargez les valeurs dans des variables locales, puis vous les manipulez, le comportement est identique et les performances très probables.

À mon avis, à moins de vous fier spécifiquement au comportement de "court-circuit", vous devriez choisir la formulation qui exprime le plus clairement votre intention. Utilisez donc && pour AND logique et & pour AND, et tout programmeur C++ expérimenté trouvera votre code facile à suivre.

37
Nemo

Lors de l'utilisation de logical et de &&, l'expression de droite ne sera pas évaluée si l'expression de gauche est false.

Beaucoup de code C/C++/C # s'appuie sur cela, comme dans: if (p != null && p->Foo()).

Pour votre exemple, je voudrais utiliser case2 (et logique). Utilisez uniquement au niveau des bits pour traiter les indicateurs de bits, etc.

Cependant, si foo () et bar () ne renvoient que bool (0, 1), alors cas1 et cas2 sont identiques.

12
Richard Schneider

Il y a une différence (enfin, deux), bien que vous ne la voyiez pas dans votre exemple.

"&" effectue une opération "AND" au niveau des bits, ce qui signifie que 0x1 & 0x1 = 0x1, mais 0x1 & 0x2 = 0x0. OTOH, "&&" est un "AND" booléen/logique, ce qui signifie qu'il traite toute valeur non nulle comme étant TRUE, donc 0x1 && 0x1 = TRUE (qui est généralement représenté par -1, c'est-à-dire que tous les uns [ou peut-être qu'il est représenté par 1 en C++. , J’oublie]), alors que 0x1 && 0x2 = TRUE également.

De plus, "&&" est en court-circuit, ce qui signifie que si le premier opérande est FALSE, le second ne sera pas évalué. Donc, alors que FALSE & null_pointer->booleanField ==> null pointer exception, FALSE && null_pointer->booleanField = FALSE.

Il peut y avoir un léger avantage de performance dans l’utilisation des opérations au niveau des bits dans certains cas, mais vous devez généralement utiliser les doubles formes lors de l’évaluation des valeurs booléennes, afin que votre code soit indépendant de la représentation précise des valeurs booléennes TRUE et FALSE.

8
Hot Licks

Algorithmiquement, il n'y a pas de différence, cependant, l'utilisation de && vous permet de "court-circuiter" le contrôle. C'est-à-dire que pour décider de cas2, si val1 est fausse, le code compilé n'a aucune raison de vérifier la valeur de val2 afin de déterminer la réponse, où cas1 exige que l'AND effectif ait lieu.

De manière réaliste, un bon compilateur le reconnaîtra et produira le même code ... cela dépend de la qualité de votre compilateur.

4
mah

" && " est un "ET logique" AND " Il évalue la deuxième expression UNIQUEMENT si la première est VRAIE

" & " est un "ET logique non conditionnel" <- (si vous jouez avec des expressions booléennes) il évalue les deux expressions


DE PLUS "&" est un opérateur "au niveau des bits", ce qui signifie qu'il fonctionne au niveau des bits. 

Cet exemple peut vous aider à mieux comprendre.

4 = 00000100  // 'four' bit set
5 = 00000101  // 'four' bit and 'one' bit set

00000100 (4) & // AND: only keep bits set in both
00000101 (5)
--------
00000100 (4)

00000100 (4) | // OR: keep bits set in either
00000101 (5)
--------
00000101 (5)

00000100 (4) ^ //  EXCLUSIVE OR: keep bits only set in one but not the other
00000101 (5)
--------
00000001 (1)
2
makiSTB

Les opérateurs logiques && et || sont utilisés lors de l'évaluation de deux expressions pour obtenir un seul résultat relationnel. L'opérateur && correspond à l'opération logique booléenne AND. Cette opération a pour résultat vrai si ses deux opérandes sont vrais et faux sinon.

L'opérateur || correspond à l'opération logique booléenne OU. Cette opération a pour résultat vrai si l'un ou l'autre de ses deux opérandes est vrai et n'est donc fausse que lorsque les deux opérandes sont faux eux-mêmes. 

0
Javeria