49

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.
Community
  • 1
  • 1
cp.engr
  • 2,291
  • 4
  • 28
  • 42
  • 7
    All non-zero integers should cast to true. I don't have a the specifications so I'm not posting an answer. – yizzlez Jul 22 '15 at 00:30
  • 1
    in C/C++ anything !0 is true and 0 is false. So, 2 is indeed true. (2 != 0) == true. – ydobonebi Jul 22 '15 at 00:32
  • 2
    @SergeyK. Did you actually read the question? – Emil Laine Jul 22 '15 at 00:32
  • 1
    it is always safe to use (n != 0) instead of (bool)n – Pouya Tehrani Jul 22 '15 at 00:33
  • The behavior I believe started with K&R C and was kept – ydobonebi Jul 22 '15 at 00:36
  • Just to add Microsoft uses -1 for true in some things – NathanOliver Jul 22 '15 at 00:39
  • @SergeyK., if you were the one who suggested it's a dupe, can you please either remove that suggestion, or quote the part there that answers my questions (if I somehow missed it)? – cp.engr Jul 22 '15 at 00:48
  • @QuinnRoundy: `bool` was introduced with C99 (actually through the use of `stdbool.h` which maps this to the built-in name `_Bool` (etc.) for compatibility with C++. K&R did not even have a boolean type, but used `int`. – too honest for this site Jul 22 '15 at 00:52
  • @NathanOliver: That would be non-standard (surprise, surprise). – too honest for this site Jul 22 '15 at 00:53
  • @Olaf (regarding True==-1 in the world of MSFT) In the C and C++ world, that would be nonstandard. However, the idea is amusing to me. The `Not` keyword in QBASIC (for **DOS**) is a bitwise NOT operator. In fact, `x And y` in the modern VB.NET is equivalent to `x & y` in C, too; all of the traditional Boolean operators have bitwise behavior in that language. With that information and the fact that `~0 == -1` on a two's complement system, I'm not surprised in the slightest that `True==-1` there; it would be like using `#define FALSE 0` followed by `#define TRUE ~(FALSE)` in C. –  Jul 22 '15 at 01:10
  • @ChronoKitsune: "MSFT"? I could add Python, Modula, Pascal, etc., but would that not lead too far? And, yes, most BASIC dialects (Apple-II, Amstrad, etc. used `-1` for "true"). One reason that time: most CPUs have/had a `not` (invert) instruction which saved one operand compared to `xor #1`to negate a truth-value. Memroy was precious that time. (disclaimer, that is certainly not the whole story). – too honest for this site Jul 22 '15 at 01:21

3 Answers3

78

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.”

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 17
    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.) – Steve Summit Jul 22 '15 at 00:48
  • Can you cite the sections of the standards that confirm your first section? – cp.engr Jul 22 '15 at 00:51
  • 2
    @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™. – Cheers and hth. - Alf Jul 22 '15 at 00:55
  • @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? – cp.engr Jul 22 '15 at 01:00
  • 2
    @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" – Cheers and hth. - Alf Jul 22 '15 at 01:06
  • @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? – cp.engr Jul 22 '15 at 17:24
  • @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. – Cheers and hth. - Alf Jul 22 '15 at 19:24
  • 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 Jul 23 '15 at 00:29
  • @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. ;-) – Cheers and hth. - Alf Jul 23 '15 at 01:59
23

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++.

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • 2
    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. – Michael Burr Jul 22 '15 at 01:04
  • @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. – too honest for this site Jul 22 '15 at 01:06
  • 2
    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`. – Cheers and hth. - Alf Jul 22 '15 at 01:08
  • 1
    @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. – too honest for this site Jul 22 '15 at 01:12
  • @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 Jul 22 '15 at 16:56
  • 1
    @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). – Michael Burr Jul 22 '15 at 17:24
  • @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. – cp.engr Jul 23 '15 at 00:32
  • 1
    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 – M.M Jan 21 '17 at 23:19
  • @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. – too honest for this site Jan 22 '17 at 02:18
1

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;
Mykyta Kozlov
  • 413
  • 3
  • 14