Casting int to bool in C/C++
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;
cp.engr
Updated on July 09, 2022Comments
-
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?:
- Casting in the reverse direction (int --> bool).
- No discussion there of non-zero, non-one values.
-
Steve Summit almost 9 yearsI don't think of
main
as returning "false" for success.main
returnsint
, not bool, and with different conventions for success/failure. (Unix system calls use yet a third mapping.) -
cp.engr almost 9 yearsCan you cite the sections of the standards that confirm your first section?
-
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 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 almost 9 yearsAnd 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 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 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 almost 9 yearsRe "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 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 ownbool
alias/#define
/enum
. That type was just added too late to the standard. -
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 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 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 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 almost 9 yearsI 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 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 almost 9 years@cp.engr: The paragraph is fine. It's correct that
main
returnsint
. 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 over 7 yearsA trap to watch out for is that some codebases (especially pre-C99 ones) may
typedef char bool
ortypedef int bool
instead of using stdbool.h -
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 almost 4 yearsThis is not casting, and doesn't answer the question.
-
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 over 2 years@AJ_Nur in C/C++ operator ! is called Logical NOT operator. In example above it is applied twice.