Есть ли разница между && и & с bool (s)? - PullRequest
31 голосов
/ 05 июля 2011

В C ++, есть ли разница между && (логическим) и & (поразрядным) между bool (s)?

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

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

case1 и case2 идентичны илиесли нет, то как именно они различаются и почему один выбирает один над другим?Является ли поразрядным и переносным bools?

Ответы [ 7 ]

37 голосов
/ 05 июля 2011

Стандарт гарантирует, что false преобразуется в ноль, а true преобразуется в единицу как целые числа:

4.7 Интегральные преобразования

...

Если тип назначения - bool, см. 4.12.Если тип источника - bool, значение false преобразуется в ноль, а значение true преобразуется в единицу.

Таким образом, эффект в приведенном вами примере гарантированно будет таким же и равен 100%.portable.

В приведенном вами случае любой порядочный компилятор может генерировать идентичный (оптимальный) код.

Однако для логических выражений expr1 и expr2 это не такв общем случае expr1 && expr2 совпадает с expr1 & expr2, поскольку && выполняет оценку "короткого замыкания".То есть, если expr1 оценивается как false, expr2 даже не будет оцениваться.Это может повлиять на производительность (если expr2 сложно) и поведение (если expr2 имеет побочные эффекты).(Но учтите, что форма & на самом деле может быть быстрее, если она избегает условного перехода ... Играть с подобными вещами из соображений производительности почти всегда плохая идея.)

Итак, для конкретногоПример, который вы приводите, когда вы загружаете значения в локальные переменные, а затем воздействуете на них, поведение идентично, и производительность, скорее всего, будет.

По моему мнению, если вы специально не полагаетесь на "короткий«Схема» поведения, вы должны выбрать формулировку, которая наиболее четко выражает ваше намерение.Поэтому используйте && для логического И и & для битового перемешивания И, и любой опытный программист на C ++ найдет ваш код легким для понимания.

13 голосов
/ 05 июля 2011

При использовании логических и && правое выражение не будет оцениваться, если левое выражение равно false.

Большая часть кода C / C ++ / C # зависит от этого, например: if (p != null && p->Foo()).

Для вашего примера я бы использовал case2 (логическое и). Использовать только побитовый при работе с битовыми флагами и т. Д.

Однако, если foo () и bar () возвращают только bool (0, 1), case1 и case2 совпадают.

8 голосов
/ 05 июля 2011

Есть разница (ну, два), хотя вы не увидите ее в своем примере.

«&» выполняет побитовую операцию «И», что означает 0x1 & 0x1 = 0x1, но 0x1 & 0x2 = 0x0. OTOH, «&&» является логическим / логическим «И», что означает, что любое ненулевое значение обрабатывается как ИСТИНА, поэтому 0x1 && 0x1 = TRUE (который обычно представляется как -1, т. Е. Все единицы [или, возможно, он представлен как 1 в C ++ я забываю]), а также 0x1 && 0x2 = TRUE.

Кроме того, "&&" является коротким замыканием, что означает, что если первый операнд имеет значение ЛОЖЬ, второй не будет оцениваться. Итак, пока FALSE & null_pointer->booleanField ==> null pointer exception, FALSE && null_pointer->booleanField = FALSE.

В некоторых случаях может быть небольшое преимущество в производительности при использовании побитовых операций, но обычно вы должны использовать двойные формы при оценке логических значений, чтобы ваш код не зависел от точного представления логических значений TRUE и FALSE.

4 голосов
/ 05 июля 2011

Алгоритмически нет никакой разницы, однако использование && позволяет вам «замкнуть» чек. То есть, чтобы решить case2, если val1 равно false, у скомпилированного кода нет причин проверять значение val2, чтобы определить ответ, где case1 требует фактического AND.

Реально, хороший компилятор распознает это и выдаст тот же код ... все зависит от того, насколько хорош ваш компилятор.

3 голосов
/ 19 сентября 2013

" && " является "условно-логическим" И "оно вычисляет ТОЛЬКО второе выражение, если первое ИСТИНА

" &"является" не-условное логическое И "<- (если вы играете с булевыми выражениями) оно вычисляет оба выражения </p>


MOREOVER " & "- это побитовый оператор, который означает, что он работаетна уровне битов.

Этот пример поможет вам лучше понять.

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)
0 голосов
/ 26 июля 2015
int a = 0, b = 10;

if(a == 1 && (b/a) == 0) cout << "This is okay\n"; // the 2nd expression is never checked as the first one is false

cout << "Bingo\n";

if(a == 1 & (b/a) == 0) cout << "This is not okay\n"; // program crashes here trying to divide by zero

cout << "Bingo\n"; // this will never get printed
0 голосов
/ 02 декабря 2012

Логические операторы && и || используются при оценке двух выражений для получения одного реляционного результата. Оператор && соответствует логической логической операции AND. Эта операция имеет значение true, если оба ее операнда имеют значение true, и false в противном случае.

Оператор || соответствует логической логической операции ИЛИ. Эта операция имеет значение true, если один из двух ее операндов имеет значение true, поэтому она ложна только тогда, когда оба операнда сами являются ложными.

...