[comp.lang.c] A builtin Boolean type

karl@haddock.ima.isc.com (Karl Heuer) (09/06/90)

This is getting off-topic for comp.lang.c, so I'm taking it to alt.lang.cfutures.

In articles <5398@harrier.ukc.ac.uk> <5409@harrier.ukc.ac.uk> mtr@ukc.ac.uk (M.T.Russell) writes:
>I'd be interested to see some experiments with adding a `bool' type to a
>C compiler (gcc?), with the following semantics:
>
>- bool has the same size and representation as int.

Why guarantee anything of the sort?  Leave it up to the implementation.  A
smart compiler can even pack them into single bits when appropriate.  (Those
12 flags declared `register bool' in main() might as well share one register!)

>- `if', `do/while', `while' and `for' demand a bool expression
>  as the test.   Note that `if (ptr)' is still allowed by the
>  implicit rewrite to `if (ptr != 0)'.

I'd strike that last sentence.  If you're going to add strict-checking
Booleans, then the user should have to make the comparison explicitly, whether
the operand is a pointer or any arithmetic type.

>- assignment and comparison between bool and arithmetic types
>  is illegal without a cast.

I suppose a cast could be legal, though I think `b=(i!=0)' and `i=(b?1:0)' are
better ways to write the conversions.

>If `typedef int bool;' was allowed as a special case, then code portability
>wouldn't be affected. ... I'd also turn on a macro __BOOL__ to indicate that
>the extension was there, so that applications could say:
>	#ifndef __BOOL__
>	typedef int bool;
>	#define TRUE 1
>	#define FALSE 0
>	#endif

Better yet, here's how to retain full backward compatibility.  I'll phrase it
in terms of what I think the ANSI Standard should have (roughly) said:

The implementation shall provide a header <bool.h>.  It defines the type
"bool" and the constants "TRUE" and "FALSE" of that type.  Including
this header may also enable strict typechecking of Booleans.  Thus, an
implementation is conforming by simply providing this header with the single
line "typedef enum { FALSE, TRUE } bool;", but a stricter implementation
may choose to say
	#pragma enable_warnings_strict_bool
	typedef __builtin_bool bool;
	#define TRUE __builtin_true
	#define FALSE __builtin_false

All operators that are conceptually Boolean (e.g. "<") return a result of type
bool, not int.  All the obvious operators and statements (e.g. "if()") expect
an expression of type bool, not int.

A bool which appears in an int context is automatically converted as if by
`b?1:0', and an int (or pointer) that appears in a bool context is
automatically converted as if by `i!=0'.  (Backward compatibility.)

Common warnings: the program has an implicit conversion involving a bool.

(Alternately, we could say that these conversions are simply illegal if
<bool.h> has been used, but I anticipate objections from the weenies who think
"j/(i+!i)" is a feature instead of a flaw.)

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
(P.S. I'd rather see YES/NO instead of TRUE/FALSE, but I expect I'm outvoted.)

karl@haddock.ima.isc.com (Karl Heuer) (09/10/90)

In article <1990Sep7.003709.4853@laguna.ccsf.caltech.edu> jimmy@tybalt.caltech.edu (Jimmy Hu) writes:
>[I don't want stronger type-checking; I want to be able to write
>"d = (a==b)*c;" and "if (flags & 0x0800)".]

In my other article in alt.lang.cfutures (to which I'm redirecting followups),
I acknowledged the existence of this style of programming.  And of course it
would continue to be legal as long as we're talking about C rather than a
completely new language; there are too many people (and dusty decks) who agree
with you.

My proposal was that the implementation could enable strict typechecking of
Booleans only when <bool.h> is included, so your code would continue to work.
Those of us who use the stricter model will write out the conversions that are
implicit in your example (i.e. "d = (a==b?1:0)*c;" and "if ((flags & 0x0800)
!= 0)", which btw should be just as efficient since that's what the compiler
will probably generate anyway, unless it really has a machine instruction that
compares two integers and sets a register to zero or one instead of setting a
condition code or something) and would use the hypothetical standard <bool.h>,
and get a compiler error rather than the wrong answer when finger slippage
puts the wrong operator in the code (the classic example being "if (a=b)", and
Yes I know that some linters already check for this specific case; I'm just
asking for a more general check).

>But as for the idea of making a standard boolean type for C, I'd have to say
>that this is going a bit too far, since it would make life difficult to the
>many programmers who actually make good use of ints as booleans.

I invoke Heuer's Law: Any feature is a bug unless it can be turned off.  (The
original example, I think, was the way the adm3a terminal would ring the bell
whenever a character was printed in column 72.  On *output*, fergodsake.)  So
leave out <bool.h>, and you continue to get ints.

>Since most languages compile booleans to ints anyways, why not use that
>extra space for your own purposes?

On the other hand, why not let the compiler make use of that space by putting
all the local Boolean objects into a single register?  (Not hard, *if* the
compiler's been told that it's dealing with Boolean rather than integer data!)
Why should I have to do it myself by defining flag bits?

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint