DawidPi
DawidPi

Reputation: 2365

C++ casting bool to int - standard

I am interrested wheather standard says anything about possible values of bool type type after casting it to integer type.

For example following code:

#include <iostream>
using namespace std;

int main() {
    bool someValue=false;
    *((int*)(&someValue)) = 50;

    cout << someValue << endl;

    return 0;
}

prints 1 even though it's forced to store value 50. Does standard specify anything about it? Or is compiler generating some method for type bool as:

operator int(){
    return myValue !=0 ? 1 : 0;
}

Also why is casting like following:

reinterpret_cast<int>(someValue) = 50;

forbidden with error

error: invalid cast from type 'bool' to type 'int'

(For all above I user GCC 5.1 compiler.)

Upvotes: 2

Views: 7879

Answers (2)

Serge Ballesta
Serge Ballesta

Reputation: 149155

This line *((int*)(&someValue)) = 50; is at least non standard. The implementation could use a lesser rank for bool (say 1 or 2 bytes) that for int (say 4 bytes). In that case, you would write past the variable possibly erasing an other variable.

And anyway, as you were said in comment, thanks to the strict aliasing rule almost any access through a casted pointer can be seen as Undefined Behaviour by a compiler. The only almost legal one (for the strict aliasing rule) would be:

*((char *) &someValue) = 50; 

on a little endian system, and

*(((char *) &someValue) + sizeof(bool) - 1) = 50; 

on a big endian one (byte access has still not be forbidden).

Anyway, as the representation of bool is not specified by the standard directly writing something in a bool can lead to true or false depending on implementation. For example an implementation could considere only the lowest level bit (true if val&1 is 1, else 0), another one could considere all bits (true for any non 0 value, false for only 0). The only thing that standard says is that a conversion of a 0 leads to false and of a non 0 leads to true.


But was is mandated by standard is the conversion from bool to int:

4.5 Integral promotions [conv.prom]

...
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

So this fully explains that displaying a bool can only give 0 or 1 - even if as the previous operation invoked UB, anything could have happen here including this display

You invoked Undefined Behaviour - shame on you

Upvotes: 4

Xarn
Xarn

Reputation: 3560

The way you are using it exhibits UB, because you write outside of the bool variable's boundaries AND you break strict aliasing rule.

However, if you have a bool and want to use it as a an int (this usually happens when you want to index into an array based on some condition), the standard mandates that a true bool converts into 1 and false bool converts into 0, no matter what (UB obviously excluded).

For example, this is guaranteed to output 52 as long as should_add == true.

int main(){
    int arr[] = {0, 10};
    bool should_add = 123;
    int result = 42 + arr[should_add];
    std::cout << result << '\n';
}

Upvotes: 7

Related Questions