Under C++ or <stdbool.h>
from C99, how is the less-than operator <
defined for boolean values?
Alternatively, explain the behaviour of this code:
#ifndef __cplusplus
#include <stdbool.h>
#endif
#include <stdio.h>
int main() {
bool b = -1;
if(b < true) {
printf("b < true\n");
}
if(b < false) {
printf("b < false\n");
}
if(true < false) {
printf("true < false\n");
}
if(false < true) {
printf("false < true\n");
}
}
Under MSVC version 10, compiled as C++ code, GCC 4.6.3-ubuntu5 compiled as C code and G++ 4.6.3-1ubuntu5 compiled as C++ code, all you get is
false < true
That is, the following inequalities are all false
:
(bool)-1 < true
(bool)-1 < false
true < false
And the following is true
:
false < true
bool seems to be defined as a (signed) integer type, false being 0, zero being 1. This explains why true > false (1 > 0) is true.
Also, comparing -1 to an unsigned number makes -1 be cast to unsigned, and on your platform this causes an integer overflow, resulting UINT_MAX (or whichever type bool has been typedeffed to). This now explains why the following expressions were false:
In C++ (and I suspect in C as well),
bool
s compare exactly as iffalse
were0
andtrue
were1
. And if the type isbool
, no values other thantrue
andfalse
are possible.When comparing
bool
to other numeric types, it will convert toint
, again withfalse
converting to0
andtrue
converting to1
.Edit: Both C++ and
stdbool.h
in C99 also force boolean values to be either 0 (false) or 1 (true) -bool b = -1;
sets the value ofb
to 1. Since1 < 1
and1 < 0
are both false, the inequalities in the question are correct.Edit: (by James) Except that the above edit isn't really correct, at least for C++. A
bool
doesn't have a value of 0 or 1, it has a value offalse
ortrue
. It's only when it is promoted toint
that the conversion creates the values of0
and1
.And as Konrad has pointed out, there is no conparison of
bool
values. The "usual arithmetic conversions" occur for the comparison operators, which means integral promotion on both of the operands, which meansbool
converts toint
(as doeschar
orshort
... or an enum).All of which is rather technical. In practice, you can remember that
false
<true
, or you can considerfalse
is 0 andtrue
is 1, whichever works best for you. The only important thing to remember is that abool
can have no other values.(Interestingly, I don't think that the bit patterns of a
bool
are imposed by the standard. An implementation could use the bit patterns0x55
and0xAA
, for example, as long as all conversions to an integral type gave 0 and 1, conversion tobool
always gave the appropriate value, etc. Including zero initialization of static variables.)And one final note:
bool b = -1;
setsb
to-1 != 0
(which istrue
, not1
, but of course,true
will convert to1
in any numeric context.Boolean values are ordered such that
false
is smaller thantrue
. According to the standard, abool
can only hold two values:true
andfalse
, so the conversions in(bool)-1
should have yieldedtrue
(as all non-0 values when converted to bool aretrue
). That is the behavior in clang and g++-4.7.The actual comparison (I believe) is done on
int
after thebool
is promoted, and it seems that the compilers you tested avoided the intermediate step of converting through bool and just promoted the actualbool
value.Here is an explaination, I haven't checked with the standard though. From your experiments it seems that the "<" operator is not defined for boolean values. What is compared is the unsigned ints that the booleans are converted to. In theory it could be possible that the standard doesn't guarantee that all "true" booleans are converted to the same value. And -1 is converted to the largest unsigned int.
As another experiment, the following code
prints 1 1 1 0
So any nonzero value is "true".
operator > and < base on this:
this false: (bool)-1 < true (bool)-1 < false because of rolling arithmetic in bool b = -1;
This makes perfect sense. The integral type => bool conversion is effectively
b = i != 0
. In order to do the<
comparison it promotes the bool to int by the rule false=>0 and true=>1. In your first case-1
will equate to true, and both will promote to 1 so it's false. Obviously 1 is never less than 0 for the second and third cases, while0 < 1
in the last case.