Casting int to bool in C/C++

127,458

Solution 1

0 values of basic types (1)(2)map to false.

Other values map to true.

This convention was established in original C, via its flow control statements; C didn't have a boolean type at the time.


It's a common error to assume that as function return values, false indicates failure. But in particular from main it's false that indicates success. I've seen this done wrong many times, including in the Windows starter code for the D language (when you have folks like Walter Bright and Andrei Alexandrescu getting it wrong, then it's just dang easy to get wrong), hence this heads-up beware beware.


There's no need to cast to bool for built-in types because that conversion is implicit. However, Visual C++ (Microsoft's C++ compiler) has a tendency to issue a performance warning (!) for this, a pure silly-warning. A cast doesn't suffice to shut it up, but a conversion via double negation, i.e. return !!x, works nicely. One can read !! as a “convert to bool” operator, much as --> can be read as “goes to”. For those who are deeply into readability of operator notation. ;-)


1) C++14 §4.12/1 “A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.”
2) C99 and C11 §6.3.1.2/1 “When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.”

Solution 2

The following cites the C11 standard (final draft).

6.3.1.2: When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.

bool (mapped by stdbool.h to the internal name _Bool for C) itself is an unsigned integer type:

... The type _Bool and the unsigned integer types that correspond to the standard signed integer types are the standard unsigned integer types.

According to 6.2.5p2:

An object declared as type _Bool is large enough to store the values 0 and 1.

AFAIK these definitions are semantically identical to C++ - with the minor difference of the built-in(!) names. bool for C++ and _Bool for C.

Note that C does not use the term rvalues as C++ does. However, in C pointers are scalars, so assigning a pointer to a _Bool behaves as in C++.

Solution 3

There some kind of old school 'Marxismic' way to the cast int -> bool without C4800 warnings of Microsoft's cl compiler - is to use negation of negation.

int  i  = 0;
bool bi = !!i;

int  j  = 1;
bool bj = !!j;
Share:
127,458
cp.engr
Author by

cp.engr

Updated on July 09, 2022

Comments

  • cp.engr
    cp.engr almost 2 years

    I know that in C and C++, when casting bools to ints, (int)true == 1 and (int)false == 0. I'm wondering about casting in the reverse direction...

    In the code below, all of the following assertions held true for me in .c files compiled with Visual Studio 2013 and Keil µVision 5. Notice (bool)2 == true.

    What do the C and C++ standards say about casting non-zero, non-one integers to bools? Is this behavior specified? Please include citations.

    #include <stdbool.h>
    #include <assert.h>
    
    void TestBoolCast(void)
    {
        int i0 = 0, i1 = 1, i2 = 2;
    
        assert((bool)i0 == false);
        assert((bool)i1 == true);
        assert((bool)i2 == true);
    
        assert(!!i0 == false);
        assert(!!i1 == true);
        assert(!!i2 == true);
    }
    

    Not a duplicate of Can I assume (bool)true == (int)1 for any C++ compiler?:

    1. Casting in the reverse direction (int --> bool).
    2. No discussion there of non-zero, non-one values.
  • Steve Summit
    Steve Summit almost 9 years
    I don't think of main as returning "false" for success. main returns int, not bool, and with different conventions for success/failure. (Unix system calls use yet a third mapping.)
  • cp.engr
    cp.engr almost 9 years
    Can you cite the sections of the standards that confirm your first section?
  • Cheers and hth. - Alf
    Cheers and hth. - Alf almost 9 years
    @cp.engr: I guess you don't have a copy of the standard or a draft. It's a good idea to get one, e.g. N3936 (latest draft) for C++14. Where, when you check it out, you find that §4.12 states "A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.". I hope this wasn't homework? It's very important to train on finding one's way in documentation, including the Holy Standard™.
  • cp.engr
    cp.engr almost 9 years
    @Cheersandhth.-Alf, no, not homework; I am a working professional. Just not well-versed in navigating the standards yet. What about C, as it relates to stdbool?
  • Michael Burr
    Michael Burr almost 9 years
    And from C++03: "An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true". I'm sure that this question is a dupe.
  • Cheers and hth. - Alf
    Cheers and hth. - Alf almost 9 years
    @cp.engr: Oh. I don't have the latest C standards, sorry. In C99 it was specified in §6.3.1.2/1 "When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1"
  • too honest for this site
    too honest for this site almost 9 years
    @MichaelBurr: I agree about the dupe for C++, but it might be not for C. I'm still searching for a corresonding paragraph in the C standard.
  • Cheers and hth. - Alf
    Cheers and hth. - Alf almost 9 years
    Re "AFAIK these definitions are identical between C and C++", no not quite. In C++ bool is a built-in type, not a macro, and there's nothing like _Bool.
  • too honest for this site
    too honest for this site almost 9 years
    @Cheersandhth.-Alf: Yes, I think I stated that clear enough by "mapped by stdbool.h to the internal name _Bool for C". It is just the names: C:_Bool (bool is a macro mapping to _Bool), C++: bool. Reason is backwards-compatibility, as much code has its own bool alias/#define/enum. That type was just added too late to the standard.
  • cp.engr
    cp.engr almost 9 years
    @MichaelBurr, I searched, and didn't find any answers on SO to what the C and C++ standards say about e.g. whether (bool)2 == true. If you can find that, please link it here.
  • cp.engr
    cp.engr almost 9 years
    @Cheersandhth.-Alf, thanks for the citations. Does the C++14 quote apply to all older versions of C++? Does the C standard quote apply to C89, C90?
  • Michael Burr
    Michael Burr almost 9 years
    @cp.engr: I agree that your question isn't a dupe of the one that's linked to in the close. I probably shouldn't have mentioned anything about dupes in my comment - sorry for that. It really doesn't matter much to me whether it's a dupe or not. It's a legit question with legit answers. The bottom line is that you should be able to count on the intuitive behavior (0 converts to false and non-zero converts to true).
  • Cheers and hth. - Alf
    Cheers and hth. - Alf almost 9 years
    @cp.engr: Regarding C++, yes. Regarding C, not exactly, because its _Bool was introduced with C99. However, the behavior that's standardized is the behavior of early 1970's K&R C, so whatever types etc. are introduced the standards will ensure this behavior.
  • cp.engr
    cp.engr almost 9 years
    I think you should revise or delete the second paragraph - main doesn't return a bool, it returns an int. It also seems...possibly off-topic? But your first paragraph + references do answer the questions I posed, so answer accepted. Thanks. :)
  • cp.engr
    cp.engr almost 9 years
    @Olaf, useful info in your answer, and thanks especially for the links. Since the other answer included citations for both C and C++, I accepted that one.
  • Cheers and hth. - Alf
    Cheers and hth. - Alf almost 9 years
    @cp.engr: The paragraph is fine. It's correct that main returns int. And it's not at all off-topic, one can't possibly find something very much more relevant. About 15 years ago I still had the idea of writing code and explanations for those who refused to think. It was a disaster. I decided to stop doing that. I think that's the right thing to do. ;-)
  • M.M
    M.M over 7 years
    A trap to watch out for is that some codebases (especially pre-C99 ones) may typedef char bool or typedef int bool instead of using stdbool.h
  • too honest for this site
    too honest for this site over 7 years
    @M.M: Thanks for the addition. Considering the various ways for hand-crafted types, it is impossible to cover all eventualities. The C tag without additional information refers to standard C, which is C11 (read the wiki). And after 18 years it is high time to cut out dead wood. Once you use the standard library (here: stdbool.h), the names defined there are reserved and shall not be defined by user code. Otherwise the code invokes undefined behaviour.
  • cp.engr
    cp.engr almost 4 years
    This is not casting, and doesn't answer the question.
  • AJ_Nur
    AJ_Nur over 2 years
    @Mykyta Kozlov, what is the keyword for this casting method? I just want to find a reference for it.
  • Mykyta Kozlov
    Mykyta Kozlov over 2 years
    @AJ_Nur in C/C++ operator ! is called Logical NOT operator. In example above it is applied twice.