Следующая часть кода предположена работать?
bool b1 = true;
bool b2 = 1 < 2;
if (b1 == b2)
{
// do something
}
Я подозреваю, что не все 'trues' равны.
В C с int
s вы можете быть правы (хотя даже здесь я думаю, что эта конкретная последовательность будет в порядке). В C ++ - да, это безопасно.
Да, булевы значения могут хранить только true или false, и вы можете сравнить значения для равенства.
Однако, некоторые плохие использования переменных bool могут привести к "неопределенному" поведению и выглядеть так, как будто оно не является ни истинным, ни ложным. Например, чтение значения неинициализированной автоматической переменной или прямой копии памяти из целых чисел.
Взгляните на следующий (плохой) пример:
bool b1 = true;
bool b2 = true;
*((char*)&b1) = 3;
if( b1 ) cout << "b1 is true" << endl;
if( b2 ) cout << "b2 is true" << endl;
if (b1 != b2) cout << "b2 is not equal to b1" << endl;
On Visual Studio 9, он показывает:
b1 is true
b2 is true
b2 is not equal to b1
Вероятно, потому что компилятор напрямую сравнил сохраненные значения.
Да, как говорили другие, bools можно сравнить на равенство в C ++. Возможно, вы думаете о том, что слышали от К.Поскольку C не имеет типа bool, логические значения представлены как целые числа. В логическом контексте любое ненулевое целое число истинно. Однако они могут иметь разные битовые комбинации и, следовательно, не быть равными. Таким образом, правилом C было не сравнивать «булевы».
Изменить: согласно комментариям, C99 имеет тип bool. Однако суть ответа заключалась в том, чтобы указать , почему идея не сравнивать булевые значения витает в воздухе. Он основан на долгой истории C до C99.
Когда вы присваиваете целое значение логическому объекту (или инициализируете логический объект целым значением), оно неявно преобразуется в истину
или false
стандартным логическим преобразованием (4.12). Итак, с точки зрения языка ваши 1
и 2
бесследно пропали задолго до того, как вы даже проведете сравнение. Они оба стали одной и той же истиной
. Здесь нет проблемы «все истины равны». Есть только одно истинное
.
Конечно, какой-нибудь компилятор, вероятно, может применить «ленивый» подход и сохранить несколько разных «истин», убедившись, что они «все равны» в момент сравнения и тому подобное, но я сомневаюсь, что это разумный / жизнеспособный подход.
Другими словами, в разумной реализации вы должны ожидать, что не только ваше сравнение будет верным, но и гораздо более сильное сравнение будет верным:
bool b1 = true;
bool b2 = 1 < 2;
if (memcmp(&b1, &b2, sizeof(bool)) == 0) {
/* We should get in here */
}
Это не гарантируется языком, но в реальной жизни это действительно так. достаточно хорошо описать физическую сторону ситуации.
В C ++ bool
- это отдельный тип с двумя возможными значениями true
и false
. Все сравнения пройдут так, как вы ожидаете. Все логические значения true
- это одно и то же, и то же самое со всеми false
. Это правда, что не все выражения, которые можно оценить как истина
или ложь
, одинаковы.
В C89, возвращаясь настолько далеко, насколько я хочу, любое нулевое значение (любого указателя или числового типа) ложно, а все остальное - истина. Это означает, что истинные значения не обязательно равны друг другу. 1
и 2
являются истинными значениями, но 1! = 2
, а 1 & 2
оценивается как 0, что неверно.
Также возможно, что ложные значения C89 не будут сравниваться равными, хотя они будут в каждой реализации, которую я когда-либо использовал. Значение нулевого указателя - это постоянное целочисленное преобразование нуля к значению указателя. Возможно, что непостоянное значение 0, приведенное к значению указателя, не будет нулевым указателем (и были системы, где нулевые указатели не все были битами 0). Следовательно, (void *) 0
является значением нулевого указателя и, следовательно, ложным, но int i; ... i = 0; ... (void *) i
возможно не быть значением нулевого указателя и, следовательно, не является ложным.
Однако в C89 все операции, которые предназначены для возврата логического значения (например, &&
или ==
]), будут возвращать 1 или 0, так что (1 == 3) == (4 == 3)
.
Проблемы возникают только тогда, когда вы привыкаете к ненулевому значению истины и забываете, что не все ненулевые значения равны.
Представьте себе:
У вас есть функция keyPressed (), которая возвращает 0, если ни одна клавиша не нажата, номер клавиши, когда клавиша нажата.
Вы написали простой переключатель в цикле:
if(keyPressed() && allow)
...
Теперь ваша компания вводит в устройства нормально открытые триггеры, и вам нужен преф.
bool key_switches_on = getPref("KeySwitchesOn");
if((keyPressed() && allow) == key_switches_on)
...
Затем вы замечаете, что "разрешить" размещено неправильно ...
if((keyPressed() == key_switches_on) && allow)
и внезапно работает только ключ номер 1.