简体   繁体   中英

Ordering of boolean values

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

In C++ (and I suspect in C as well), bool s compare exactly as if false were 0 and true were 1 . And if the type is bool , no values other than true and false are possible.

When comparing bool to other numeric types, it will convert to int , again with false converting to 0 and true converting to 1 .

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 of b to 1. Since 1 < 1 and 1 < 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 of false or true . It's only when it is promoted to int that the conversion creates the values of 0 and 1 .

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 means bool converts to int (as does char or short ... or an enum).

All of which is rather technical. In practice, you can remember that false < true , or you can consider false is 0 and true is 1, whichever works best for you. The only important thing to remember is that a bool 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 patterns 0x55 and 0xAA , for example, as long as all conversions to an integral type gave 0 and 1, conversion to bool always gave the appropriate value, etc. Including zero initialization of static variables.)

And one final note: bool b = -1; sets b to -1 != 0 (which is true , not 1 , but of course, true will convert to 1 in any numeric context.

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, while 0 < 1 in the last case.

Boolean values are ordered such that false is smaller than true . According to the standard, a bool can only hold two values: true and false , so the conversions in (bool)-1 should have yielded true (as all non-0 values when converted to bool are true ). That is the behavior in clang and g++-4.7.

The actual comparison (I believe) is done on int after the bool is promoted, and it seems that the compilers you tested avoided the intermediate step of converting through bool and just promoted the actual bool value.

operator > and < base on this:

true == (1)
false == (0)

this false: (bool)-1 < true (bool)-1 < false because of rolling arithmetic in bool b = -1;

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:

((bool)-1) < true i. e. UINT_MAX < 1
((bool)-1) < false i. e. UINT_MAX < 0
true < false i. e. 1 < 0

For C++ just false < true

For C is more difficult to answer. I see

typedef char _Bool; /* For C compilers without _Bool */ typedef char _Bool; /* For C compilers without _Bool */ in my stdbool.h

Seems, that if compiler support _Bool , it works as in C++ and automatically converts to 0/1, but if not it should work as char and it'll be b < true , b < false if char is signed

For me (int)(bool) -1 is 1 even in C, so bool is defined as not char

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

#include <iostream>

int main()
{
std::cout<< (((bool)1) == true) << "\n";
std::cout<< (((bool)2) == true) << "\n";
std::cout<< (((bool)0) == false) << "\n";
std::cout<< (((bool)1) == false) << "\n";
  return 0;
}

prints 1 1 1 0

So any nonzero value is "true".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM