Is the following piece of code supposed to work?
bool b1 = true;
bool b2 = 1 < 2;
if (b1 == b2)
{
// do something
}
I suspect that not all 'trues' are equal.
Is the following piece of code supposed to work?
bool b1 = true;
bool b2 = 1 < 2;
if (b1 == b2)
{
// do something
}
I suspect that not all 'trues' are equal.
In C with int
s you might have a point (although even there I think this particular sequence would be OK). In C++, yes this is safe.
Yes, as others have said bools can be compared for equality in C++. You may be thinking of things you heard from C. Since C has no bool type, booleans are represented as integers. In a boolean context any non-zero integer is true. However, they might have different bit patterns and thus not be equal. So the rule in C was not to compare 'booleans'.
Edit: per comments, C99 has a bool type. However the point of the answer was to indicate why the idea of not comparing bools is floating around. It is based on the long history of C, prior to C99.
Yes, boolean values can only store true or false, and you can compare the values for equality.
However, some bad uses of bool variables can lead to "undefined" behaviours and might look as if it is neither true nor false. For example reading the value of an uninitialized automatic variable or direct memory copy from integers.
Take a look at the following (bad) example:
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, it shows:
b1 is true
b2 is true
b2 is not equal to b1
Probably, because the compiler has directly compare the values stored.
The problems are only when you get used to non-zero being true and forget that not all non-zeros are equal.
Imagine this:
You have a function keyPressed() that returns 0 on no key pressed, number of key when a key is pressed.
You wrote a simple switch in a loop:
if(keyPressed() && allow)
...
Now your company introduces normally open triggers in the devices and you need a pref.
bool key_switches_on = getPref("KeySwitchesOn");
if((keyPressed() && allow) == key_switches_on)
...
Then you notice "allow" is placed wrong...
if((keyPressed() == key_switches_on) && allow)
and suddenly only key number 1 works.
When you assign an integral value to a boolean object (or initialize boolean object with an integral value) it is implicitly converted to a true
or false
by a standard boolean conversion (4.12). So, from the language point of view, your 1
and 2
are gone without a trace long before you even do the comparison. They both have become the very same true
. There's no "all trues are equal" issue here. There's only one true
.
Of course, some compiler might probably take a "lazy" approach and keep multiple different "trues" around, making sure that they "all are equal" at the moment of comparison and such, but I doubt this is a reasonable/viable approach.
In other words, in a reasonable implementation you should expect not only your comparison to hold true, but a much stronger comparison to be true as well:
bool b1 = true;
bool b2 = 1 < 2;
if (memcmp(&b1, &b2, sizeof(bool)) == 0) {
/* We should get in here */
}
This is not guaranteed by the language, but in real life it does describe the physical side of the situation quite well.
In C++, bool
is its own type, with the two possible values true
and false
. All comparisons will go as you expect. All true
boolean values are the same thing, and the same with all false
. It is true that not all expressions you can evaluate to true
or false
are the same.
In C89, to go back as far as I want to, any zero value (of any pointer or numeric type) is false, and anything else is true. This means that true values aren't necessarily equal to each other. 1
and 2
are true values, but 1 != 2
, and 1 & 2
evaluates to 0, which is false.
It's also possible for C89 false values to not compare equal, although they will on every implementation I've ever used. A null pointer value is a constant integral zero cast to a pointer value. It is possible for a non-constant value 0 cast to a pointer value to not be a null pointer (and there have been systems where null pointers were not all bits 0). Therefore, (void *)0
is a null pointer value, and hence false, but int i;...i = 0;...(void *)i
could possibly not be a null pointer value, and hence not false.
However, in C89, all operations that intend to return a boolean value (like &&
or ==
, for example), will return 1 or 0, so that (1 == 3) == (4 ==3)
.