Сведения о вопросе

Kimsanov

07:10, 1st August, 2020

Теги

Использование побитовых операторов для булевых чисел в C++

Просмотров: 430   Ответов: 4

Есть ли какая-либо причина не использовать побитовые операторы &, |, и ^ для значений "bool" в C++?

Я иногда сталкиваюсь с ситуациями, когда я хочу, чтобы одно из двух условий было истинным (XOR), поэтому я просто бросаю оператор ^ в условное выражение. Я также иногда хочу, чтобы все части условия были оценены, является ли результат истинным или нет (вместо короткого замыкания), поэтому я использую & и |. Мне также иногда нужно накапливать логические значения, и &= и |= могут быть весьма полезны.

Я получил несколько поднятых бровей, когда делал это, но код все еще значим и чище, чем это было бы в противном случае. Есть ли какая-то причина NOT использовать их для bools? Есть ли современные компиляторы, которые дают плохие результаты для этого?



  Сведения об ответе

park

12:53, 11th August, 2020

|| и && являются логическими операторами, и встроенные из них гарантированно возвращают либо true , либо false . Больше ничего.

|, & и ^ являются побитовыми операторами. Когда область чисел, с которой вы работаете, просто 1 и 0, то они точно такие же, но в тех случаях, когда ваши булевы не являются строго 1 и 0 –, как в случае с языком C –, вы можете в конечном итоге получить какое-то поведение, которого вы не хотели. Например:

BOOL two = 2;
BOOL one = 1;
BOOL and = two & one;   //and = 0
BOOL cand = two && one; //cand = 1

В C++, однако, тип bool гарантированно будет только либо true , либо false (которые неявно преобразуются соответственно в 1 и 0 ), так что это меньше беспокоит с этой позиции, но тот факт, что люди не привыкли видеть такие вещи в коде, является хорошим аргументом для того, чтобы не делать этого. Просто скажите b = b && x и покончите с этим.


  Сведения об ответе

ЯЯ__4

21:06, 1st October, 2020

Две основные причины. Короче говоря, подумайте хорошенько; для этого может быть хорошая причина, но если в ваших комментариях есть явное выражение be VERY, потому что оно может быть хрупким и, как вы сами говорите, люди обычно не привыкли видеть такой код.

Побитовый xor != Логическое xor (кроме 0 и 1)

Во-первых, если вы оперируете значениями , отличными от false и true (или 0 и 1, как целые числа), оператор ^ может ввести поведение, не эквивалентное логическому xor. Например:

int one = 1;
int two = 2;

// bitwise xor
if (one ^ two)
{
  // executes because expression = 3 and any non-zero integer evaluates to true
}

// logical xor; more correctly would be coded as
//   if (bool(one) != bool(two))
// but spelled out to be explicit in the context of the problem
if ((one && !two) || (!one && two))
{
  // does not execute b/c expression = ((true && false) || (false && true))
  // which evaluates to false
}

Кредит пользователю @Patrick для выражения этого в первую очередь.

Порядок операций

Во-вторых, | , & и ^ , как побитовые операторы, не имеют короткого замыкания. Кроме того, несколько побитовых операторов, связанных вместе в одном операторе-даже с явными скобками-могут быть переупорядочены оптимизирующими компиляторами, поскольку все 3 операции обычно коммутативны. Это важно, если важен порядок операций.

Иначе говоря

bool result = true;
result = result && a() && b();
// will not call a() if result false, will not call b() if result or a() false

не всегда будет давать тот же результат (или конечное состояние), что и

bool result = true;
result &= (a() & b());
// a() and b() both will be called, but not necessarily in that order in an
// optimizing compiler

Это особенно важно, потому что вы можете не контролировать методы a() и b() , или кто-то другой может прийти и изменить их позже, не понимая зависимости, и вызвать неприятную (и часто только выпускающую сборку) ошибку.


  Сведения об ответе

COOL

23:42, 7th August, 2020

Я думаю

a != b

это то, что ты хочешь


  Сведения об ответе

LIZA

17:06, 25th August, 2020

Поднятые брови должны сказать вам достаточно, чтобы прекратить это делать. Вы не пишете код для компилятора, вы пишете его сначала для своих коллег-программистов, а затем для компилятора. Даже если компиляторы работают, удивлять других людей-это не то, что вам нужно, - побитовые операторы предназначены для битовых операций, а не для булов.
Я полагаю, вы также едите яблоки с fork? Это работает, но удивляет людей, поэтому лучше этого не делать.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться