17

The bool data type is commonly represented as 0 (as false) and 1 (as true). However, some say that true values can be represented by a value other than 1. If the later statement is true, then the following expression may be incorrect.

bool x = 1;
if (x==1)
    Do something..

I am wondering if the following statements would work as desired and expected on commonly used compilers.

  1.  

    bool x = 1;
    if (x==1)
        Do something.
    
  2.  

    bool y = 0;
    if (y>0.5)
        Do something..
    
  3.  

    bool z = 1;
    if(z>0.5)
        Do something...
    
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
rezabakhsh
  • 301
  • 2
  • 5
  • 6
    [This implicit conversion reference](https://en.cppreference.com/w/cpp/language/implicit_conversion) might be helpful to read. – Some programmer dude May 20 '19 at 09:46
  • 1
    According to the boolean conversions rules: "The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true." – vahancho May 20 '19 at 09:48
  • 3
    The conversions to and from `bool` do not depend on how a `bool` is represented. Your code will work even if `true` is represented as 39 and `false` as 10003. – molbdnilo May 20 '19 at 10:04
  • 1
    My gut feeling is that there's something deeper behind this question. Maybe not about the *implicit conversions*, which can be looked up and argued about based on the spec, but rather about the "actual representation". Maybe what happens during hacky contortions along the lines of `double x = *(reinterpret_cast>(&someBool));` (i.e. when brutally exposing the actual representation - not sure about the exact syntax from the tip of my head, or whether it causes UB at some point...) – Marco13 May 20 '19 at 13:50
  • Re, "I am wondering if the following statements would work as desired..." That depends on what you desire. If `y` is a bool variable, and you write `if(y){...}` then your desire is obvious to anybody who reads your code. If, on the other hand, you write `if(y>0.5){...}` That's somewhat of a head scratcher. The reader can consult the C language standard to see what _it_ says about the construct, but that still won't tell the reader what _you_ intended. – Solomon Slow May 20 '19 at 14:14
  • 1
    FWIW, it's looking likely that [this paper](http://wg21.link/p0907) will make its way into the standard, at which point 0 and 1 will be the only allowed representations of true and false. – chris May 20 '19 at 14:46
  • 1
    What exactly is the hindrance to using `true` and `false`? I mean, pretty much the whole purpose of a `bool` type is to be a "boolean", not a "number", from an imaginary/theoretical point of view (even though it is technically a number, and converts to a number). Otherwise you could just as well use `char` with the values `0` and `1`. – Damon May 20 '19 at 16:43
  • @Damon The only example I can think of from the top of my head is using a bool to index into an array which is at least less code and possibly more efficient if the compiler isn't good. – Voo May 20 '19 at 20:02

5 Answers5

15

§4.5 of the C++ standard says:

An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true becoming one.

regarding 2 and 3, type conversion takes place so the statements will work as desired

Martin Konrad
  • 1,075
  • 1
  • 10
  • 20
akib khan
  • 451
  • 4
  • 9
  • 4
    Where is this quotation from? – Brian Bi May 20 '19 at 14:52
  • 2
    @Brian: C++ is formally documented by an ISO standard (14882). So on Stack Overflow, such quotations that omit the source document are assumed to reference the _then-current_ C++ Standard. As this is a 2019 answer, that means the quote is from ISO 14882:2017 (aka C++17). – MSalters May 20 '19 at 15:07
  • 5
    @MSalters I know for a fact this is not from ISO 14882:2017. – Brian Bi May 20 '19 at 15:07
  • 3
    I suspect it's from the *C++03 standard*, but I don't have a copy handy to check. – Brian Bi May 20 '19 at 15:08
  • This text only specifies what the conversion does, not when it is applied. Some of OP's examples convert bool to float, not bool to int. The specification for each operator specifies which conversions are applicable to that situation. – M.M May 20 '19 at 23:15
9

According to the rule of Boolean conversions:

A prvalue of integral, floating-point, unscoped enumeration, pointer, and pointer-to-member types can be converted to a prvalue of type bool.

The value zero (for integral, floating-point, and unscoped enumeration) and the null pointer and the null pointer-to-member values become false. All other values become true.

Then

bool x = 1; // x will be true
bool y = 0; // y will be false
bool z = 1; // z will be true

For the 1st case, if (x==1), x will be promoted to int,

the type bool can be converted to int with the value false becoming ​0​ and true becoming 1.

then (x==1) is true.

For the second case, if (y>0.5), y will be promoted to int with value 0, then converted to double for the comparison;

If the operands has arithmetic or enumeration type (scoped or unscoped), usual arithmetic conversions are performed on both operands following the rules for arithmetic operators. The values are compared after conversions:

and

If the operand passed to an arithmetic operator is integral or unscoped enumeration type, then before any other action (but after lvalue-to-rvalue conversion, if applicable), the operand undergoes integral promotion.

...

  • Otherwise, if either operand is double, the other operand is converted to double

then y>0.5 is false.

For the third case, if (z>0.5), z will be promoted to int with value 1, then converted to double for the comparison; then z>0.5 is true.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 1
    "y will be promoted to int with value 0" - this is incorrect. `y` will be converted to `double`. As covered by your quote "Otherwise, if either operand is `double`, the other operand is converted to `double`". (`>` is not an arithmetic operator). Same goes for `z` – M.M May 20 '19 at 13:17
  • @M.M Shouldn't *integral promotion* be performed firstly? As I quoted "If the operand passed to an arithmetic operator is integral ... then before any other action ... the operand undergoes integral promotion." – songyuanyao May 20 '19 at 14:47
  • `>` is not an arithmetic operator – M.M May 20 '19 at 23:14
  • @M.M Yes, but I think [the rule](https://en.cppreference.com/w/cpp/language/operator_comparison#Arithmetic_comparison_operators) is the same. "If the operands has arithmetic or enumeration type (scoped or unscoped), usual arithmetic conversions are performed on both operands following the rules for arithmetic operators. The values are compared after conversions:" – songyuanyao May 21 '19 at 00:21
  • Your quote in your last comment is correct, and the behaviour of "usual arithmetic conversions" is quoted in your answer, namely "Otherwise, if either operand is double, the other operand is converted to double" – M.M May 21 '19 at 01:15
6

if (x==1) is not incorrect. All true value representations are converted to 1 when you convert a boolean to a numeric type.

Given bool z=true, if(z>0.5) will be true, because 1.0 is greater than 0.5.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 1
    *"not incorrect"* - [double negative](https://www.podtrac.com/pts/redirect.mp3/media.blubrry.com/grammargirl/traffic.libsyn.com/grammar/gg_666.mp3) – Peter Mortensen May 20 '19 at 13:11
  • even if casting is possible I think we should not do that. We should explicitly compare variable of right same type even if it is more verbose. I see some compilation error which raise up for those cases – Narcisse Doudieu Siewe Jul 16 '20 at 14:46
4

bool has only two values, and they are true and false. 1 and 0 are integer literals and as such they can be converted to bool. You have to consider that the conversion works in both directions, but you do not necessarily get back the same integer:

int a = 5;
bool b = a; // int -> bool conversion
int c = b;  // bool -> int conversion
std::cout << a << " " c;

prints:

5 1

Any integer value other than 0 gets converted to true, but true gets always converted to 1.

Keeping this in mind, all your examples will work as expected. However, note that bools main purpose is that we can use true and false in our code instead of having to give numbers as 0 and 1 special meaning. It is always better to be explicit, so when you mean true you better write true not 1.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

A relevant question here is "why do we even allow comparison between a bool and an int?".

The answer is backward compatibility and compromise, because C and C++ used to recommend integers to store Boolean values. So there was a lot of code that

  1. Should keep working in spite of new language rules, such that relational operators return a bool instead of an int.
  2. Allow you to upgrade old code by changing the declaration of a Boolean variable with a minimum of follow-up changes in the rest of the code.

Other languages may be cleaner in this respect, but the bool type has apparantly been a success.

Dag B
  • 621
  • 3
  • 8