I found out that some languages like C don't have support for boolean variables and programmers use integers with values of 0 and 1 instead. Is there any specific reason why some languages moved away from this other than improved readability?
-
C99 standardized booleans: pubs.opengroup.org/onlinepubs/9699919799/basedefs/…– BlrflAug 4, 2015 at 10:39
-
8I'm pretty sure that at least some of C's predecessors had explicit boolean types (for example ALGOL 60, ALGOL 68, PASCAL), so the question should rather be why did C move away from that?– Jörg W MittagAug 4, 2015 at 10:50
-
4Because zero and one are not type-safe. It's also not zero and one; it's more like zero and non-zero. Languages like Java and C# still use negative, zero and positive for ordering purposes.– Robert HarveyAug 4, 2015 at 14:54
-
2@JörgWMittag: For the same reason C moved away from so many other things that Pascal got right before C got them wrong: it was created by a hack who cared more about painting a smiley-face over assembly and calling it a high-level language than about actual tested-and-true good language design.– Mason WheelerAug 4, 2015 at 18:02
-
"Programmers use integers with values of 0 and 1 instead" <-- This is not true. In C we represent false with 0, but true can be represented by any other value. I.e. if (x) { ... } gets executed as long as x is not zero. Furthermore, most functions don't promise to return a specific value like 1 for true. They just say they return some nonzero value (i.e. "true")– BrandinAug 4, 2015 at 19:13
5 Answers
Built in boolean types are there to more succinctly express true or false (most typically in condition statements). The bool goes directly to being able to write a conditional that is semantically clear - testing for and creating boolean results in the code. It would be more natural and clearer to be able to use a genuine boolean type.
Originally C used integral values (there is now a type _Bool
) with the condition that false was 0 (or NULL in pointer tests) and true was not false (not necessarily just 1). Which is generally all "well", but you then can't expressly/directly test for and store a true condition (only for a not false).
-
What do you mean by "you can't directly test for a true condition". What's wrong with
if (x) { do_something(); }
This will do_something only if x is true.– BrandinAug 4, 2015 at 19:33 -
I mean,
== true
. Your test condition evaluates to "true" for any value other than 0, being false. There isn't a single true value, it's either false or not false.– NiallAug 4, 2015 at 19:43 -
1The way to test if x is true in C is just to write
if (x) ...
. That directly tests for whether it is "not false" or false (i.e. whether it is true or false)– BrandinAug 4, 2015 at 20:52 -
@Niall Explicitly testing for
== true
is bad style in most programming languages I know. If you have a boolean, just use its value directly! Aug 4, 2015 at 22:56 -
Correct, I'm not talking about style (the
if (x==true)
, I don't think the question was either. Point is there isn't a single true value, there are many (i.e. not 0).– NiallAug 5, 2015 at 4:09
They are semantically different types, used for different purposes, so it's very useful for the type checker to be able to distinguish between them. Take this infamous bug, for example:
if (x = 1)
...
In most languages, the type checker will catch this, because it is expecting a boolean, but got an int (or unit/void in languages where assignments don't return their value). C is one of very few languages that permit this particular bug.
-
Which bug is this referring to? I can see that the
if
statement is evaluating what's returned from an assigment, instead of the current value of the variable; but it depends on the language, and it seems liketrue
/false
would have the same issue. It seems like there's something I'm not personally following. Aug 4, 2015 at 15:53 -
@Panzercrisis it would not typecheck at all in static languages, you wouldn't even be able to compile– ZaviorAug 4, 2015 at 16:09
-
@Panzercrisis - also
(x=1)
has a chance to evaluate to true unless x is set asfinal
- some languages do not have this construct(final) so the ability to assign a value to a variable (assuming convention is followed in variable nomenclature, ie in php it would be($x =1)
) is what is evaluated Aug 4, 2015 at 16:19
It proved very helpful to standardize them.
You'd think 0 is 'false' and 1 is 'true' is easy. However, it is also common to see -1 for 'true,' because in 2's complement notation, that is all 1's. The more generalized version is also used: 0 for false and non-zero for true. However, that leads to interesting situations where you can bitwise AND two non-zero values together and get a false value, so much consternation occurred.
In the end, the confusion of using different boolean conventions from library to library was sufficient. We now have bool to handle that.
(And even then, it doesn't always work if you get code from different compilers and try to link them!)
-
By way of contrast... in classic unix/linux shell zero is success and non-zero is a failure... I presume this is because a program typically succeeds in 1 way but can fail in a multitude of different ways. (BTW: for a short window in the 1980s the 'csh' had these reversed.
true && echo true; false || echo false
) Aug 28, 2015 at 23:59
Just for readability, though this doesn't mean anything. There are no integral types for tri-state values even though they are very common in programming (eg comparison operators return one of 3 states)
-
2There is, however, thedailywtf.com/articles/What_Is_Truth_0x3f_ Aug 4, 2015 at 10:29
-
5In many languages, comparison returns an
enum { LT, EQ, GT }
, in Haskell it returns an instance ofOrdering
which has three data constructorsLT, EQ, GT
, Scalaz'sOrdering
issealed
and has three implementationsLT
,EQ
, andGT
. Aug 4, 2015 at 10:49 -
@JörgWMittag sure, but that's only 2 languages and is not an integral type like bool but an enum. I couldn't (sensibly) use that type for the states of a tri-state checkbox. Perhaps the reason we have bool and not tristate is that no-one could think of good, generic names for the 3 states :)– gbjbaanbAug 4, 2015 at 12:46
-
1@gbjbaanb booleans aren't integrals, so bools are the ones that are out of place, not the enums.– DovalAug 4, 2015 at 16:43
The main reasons are:
1. Use cases for booleans are extremely common.
I'll assume the well-known convention that 0 means false and 1 means true is enough proof of this.
2. We want type safety.
An integer can do everything that a boolean can, and a lot more, so it's not like we were missing any functionality.
But, if we used integers to represent booleans, then our "booleans" would be able to do things that booleans shouldn't be able to do (such as addition and subtraction), and they'd be able to interact with "real integers" in ways that don't make any sense (strictly speaking, true should not be equal to 1).
We usually use the term "type safety" to refer to issues like this. Using integers to represent booleans is not a "type-safe" solution.
Type safety is generally considered a very good thing, especially in statically typed languages where the compiler is effectively checking your program for type errors on every compilation. Given that true == 42
is not a valid or meaningful comparison, it would be nice if the compiler simply did not allow it and forced us to go fix that piece of code. The "improved readability" you mention in your question is another typical benefit.
3. A user-defined type (i.e., a class or struct) cannot represent a boolean correctly, so it would have to be a primitive or built-in type
For many of us, this is the really interesting and non-obvious part. In the case of C++, this issue is explained quite thoroughly by Herb Sutter's Guru of the Week #26. I'll quote his summary here:
A typedef ... bool wouldn't allow overloading on bool.
A #define bool wouldn't allow overloading either and would wreak the usual havoc of #defines.
An enum bool would allow overloading but couldn't be automatically converted from a conditional expression (as in "b = (i == j);").
A class bool would allow overloading but wouldn't let a bool object be tested in conditions (as in "if( b )") unless it provided an automatic conversion to something like int or void*, which would wreak the usual havoc of automatic conversions.
Yes, we really did need a builtin bool! And, finally, there's one more thing (related to overloading) that we couldn't have done otherwise, either, except perhaps with [a class]: specify that conditional expressions have type bool.
So C++ can't do non-primitive booleans. At the risk of oversimplifying the differences between langauges, if you can't do something in C++, there's a good chance you can't do it in any of the other mainstream OOP langauges. I believe the C# implementation would get exactly as close as the C++ one, but no closer, and Java would be significantly worse off since it deliberately doesn't offer operator overloading or implicit conversions.