Answer to Tricky booleans
The reason why you can do this is that booleans are usually (at least on X86, X86-64 and Arm) stored as an entire byte in memory. This means that it has 256 different states, of wich only 0 and 1 is usually used. However, with the help of some undefined behavior, we can easily construct booleans that contains any value. For example:
bool createBool(int id) {
union T {
bool b;
char v;
};
T t;
t.v = id;
return t.b;
}
Ever noticed that doing cout on a boolean prints a number instead of true or false? This is
ususally the actual value of the boolean variable, and it can therefore be used to see that you
have succeeded. In this case, we will construct the boolean 1 and the boolean 2.
So why does both of these count as true, but are still not equal to each other?
The simple answer is that you have one false and 255 different true. The compiler will not
give you anything but one of the true values unless you do something strange, so it usually
appears as if there is only one true value.
I am not sure about why booleans are implemented like this, but my guess is that it is all about
performance and simplicity in the end. In C, there were no booleans, but if you did if (x), x
would be considered to be true if it was nonzero and false if it was zero. I guess the booleans
in C++ follows this to make the implementation easier in the compiler, but it also makes sense from
a performance perspective, since there is usually some kind of branch if zero/nonzero instruction
in the CPU, and these checks are therefore easily implemented like this.
Comparision between two booleans is a little trickier if we consider the zero-nonzero rule.
To implement equals correctly, we would have to chain a few instructions together, possibly like this:
bool bool_equals(bool a, bool b) {
if (a) {
if (b) {
return true;
}
} else {
if (!b) {
return true;
}
}
return false;
}
So my guess here is that since the compiler can assume that booleans only ever contains 0 or 1, we
can implement the equality as a regular comparision instead. This is the reason why our two boolean
values does not compare equal, while both are considered to be true. This also shows what undefined
behavior can do to your code sometimes. Even if you do not go through a lot of trouble creating this
kind of booleans, they can still appear if you forget to initialize a variable. And this kind of
errors are not easy to track down, since you usually assume that booleans are either true or false,
when they can actually be one of 256 values, out of which one is considered false.
Comments
New comment
You can use GitHub flavored markdown here. Parsed by Parsedown, which does not support all of GitHub's features. For example, specifying the language of code listings is not supported.