[comp.lang.c] Time to standardize "true" and "false"

nagle@well.UUCP (John Nagle) (09/22/89)

     I would like to suggest that the time has come to standardize the
Boolean values in C.  Most programs have definitions of these, but they
differ and clash.  As the typing rules become ever tighter, and the number
of commercial libraries available grows, this becomes a more and more
serious problem.  Commercially published libraries have spellings such
as "TRUE", "true", and "True", forms of definition including "#define",
"const", and "enum", and Boolean types (spelled variously) defined
as "char", "unsigned char", "unsigned short", and "enum".

     This has got to stop.

     I would suggest that the standardized definition be

	const boolean (false=0, true=1);

which follows the convention that predefined types in C are all lower
case.  The explicit values for "false" and "true" are given, although
redundant, to make the point that those values are part of the specification
and are not an accident of the ordering in the definition. 

     It should be mandated that this definition be a part of the C
and C++ header files, preferably in an ANSI-specified file.
"stddef.h" seems a likely choice, but this is open to discussion.

     If it's too late to fix this in C, it should be fixed in C++, where
typing is taken more seriously.

					John Nagle

blarson@basil.usc.edu (bob larson) (09/22/89)

In article <13730@well.UUCP> nagle@well.UUCP (John Nagle) writes:
>
>     I would like to suggest that the time has come to standardize the
>Boolean values in C.
[...]
>     I would suggest that the standardized definition be
>	const boolean (false=0, true=1);

Why don't we just change the languae so it has this stuff built in?
Perhaps we can find a way that dosn't add more keywords to the
language... the little-known keyword "int" should be able to do
double-duty as boolean, and the keywords 0 and 1 should work just fine
as false and true.  Let's see what other changes are needed to the
languge... none.  Gee, it seems that maybe this was one of the uses
theese keywords were designed for. :-)

-- 
Bob Larson	Arpa:	blarson@basil.usc.edu
Uucp: usc!basil!blarson

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/22/89)

In article <13730@well.UUCP> nagle@well.UUCP (John Nagle) writes:
>     I would suggest that the standardized definition be
>	const boolean (false=0, true=1);

I don't know what that is supposed to mean; it's not C.

>     It should be mandated that this definition be a part of the C
>and C++ header files, preferably in an ANSI-specified file.

The result of a nominally Boolean expression in C is well-defined;
it has int type with value 1 for true, 0 for false.

>"stddef.h" seems a likely choice, but this is open to discussion.

Not really.

There is no problem insofar as the C Standard goes; "bool", "true",
etc. are not reserved words and have no special meaning.  The
problem you describe comes about only when you #include headers
for several unrelated (or at least uncoordinated) libraries.
In such a case, this is merely a small part of a name-space clash
problem.  You should address the general problem instead of one
small aspect of it.

newsuser@lth.se (LTH network news server) (09/22/89)

In article <13730@well.UUCP> nagle@well.UUCP (John Nagle) writes:
>
>     I would like to suggest that the time has come to standardize the
>Boolean values in C.

I completely agree that a boolean data type is needed in C++.  I
think the definition should define the following properties:

	1.  The data type is called "boolean".
	2.  The allowed values are "false" and "true".
	3.  int(false) = 0 and int(true) = 1
	4.  boolean(0) = false, other values are true

I do not know if implicit conversion boolean <==> int should be allowed.

In the time before C++ 2.0, it was quite common to define a boolean type
as an enumeration:

	enum boolean {false, true};

Unfortunately (in this case), C++ no longer allows implicit conversion
int ==> enum, so the result of a comparison must be explicitly type cast:

	boolean b;
	b = (i == 3);		// warning
	b = boolean(i == 3);	// ok

This is rather clumsy.  We cannot define our own operator functions on
the boolean data type, because one of the arguments must be a class object.

	boolean operator == (boolean x, boolean y) {...}	// error

I do not understand exactly why this restriction is required, but apparently
it is.  Please enlighten me.

What remains is to define a class for boolean.  This is not easy to
make as efficient as the built in types, but the problem is mostly in
the lack of optimization in the code generators.  I have tried; you
will find my attempt to define a boolean below.  Note that I have not
defined the operators && and || -- I do not think we can achieve the
"short circuit" evaluation we're used to with a user-defined operator.

Dag Michael Bruck
--
Department of Automatic Control		Internet:  dag@control.lth.se
Lund Institute of Technology
P. O. Box 118				Phone:	+46 46-108779
S-221 00 Lund, SWEDEN			Fax:    +46 46-138118

==============================================================================

// Boolean data type

enum {false, true};

class Boolean {
public:
  Boolean()		{ val = false; }
  Boolean(int i)	{ val = (i != false); }
  Boolean(const Boolean& b)	{ val = b.val; }
  // Any non-zero value is true; default value is false.

  operator int()	{ return val; }
  // Type cast boolean => integer.

  void operator &= (const Boolean& b)	{ val &= b.val; }
  void operator |= (const Boolean& b)	{ val |= b.val; }
  void operator ^= (const Boolean& b)	{ val ^= b.val; }
  // Operator assignment.

  friend Boolean operator & (const Boolean&, const Boolean&);
  friend Boolean operator | (const Boolean&, const Boolean&);
  friend Boolean operator ^ (const Boolean&, const Boolean&);
  friend Boolean operator ! (const Boolean&);
  friend Boolean operator == (const Boolean&, const Boolean&);
  friend Boolean operator != (const Boolean&, const Boolean&);
  // These operators need access to the internal representation.

private:
  int	val;
  Boolean(long i) { val = int(i); }	// no check
};

inline Boolean operator & (const Boolean& p, const Boolean& q)
{ return long(p.val & q.val); }

inline Boolean operator | (const Boolean& p, const Boolean& q)
{ return long(p.val | q.val); }

inline Boolean operator ^ (const Boolean& p, const Boolean& q)
{ return long(p.val ^ q.val); }

inline Boolean operator ! (const Boolean& p)
{ return long(!p.val); }

inline Boolean operator == (const Boolean& p, const Boolean& q)
{ return long(p.val == q.val); }

inline Boolean operator != (const Boolean& p, const Boolean& q)
{ return long(p.val != q.val); }

// Note: there are no && and || operators.


Boolean f(Boolean b)
{
  return !b;
}


main()
{
  Boolean p, q, r;

  r &= p;
  r = p & q;
  r = f(p);
}
-- 
Department of Automatic Control		Internet:  dag@control.lth.se
Lund Institute of Technology
P. O. Box 118				Phone:	+46 46-108779
S-221 00 Lund, SWEDEN			Fax:    +46 46-138118

dog@cbnewsl.ATT.COM (edward.n.schiebel) (09/22/89)

From article <13730@well.UUCP>, by nagle@well.UUCP (John Nagle):

>      I would like to suggest that the time has come to standardize the
> Boolean values in C.  
HERE HERE!!!

	-Ed Schiebel.
	

nagle@well.UUCP (John Nagle) (09/23/89)

Correction: the definition should have read:
>	enum boolean (false=0, true=1);
     
       Doug Gwin at BRL points out that namespace clashes are a more
general problem in C.  But this isn't a namespace-control problem.
It's not that we want every package to have its own definition of
"boolean", all kept straight in some way and with conversion functions
between package A's "boolean" and package B's "boolean" somehow provided.

       "boolean" really ought to be part of the language, and the logical
operators should return results of type "boolean", but it's too late in
the history of C/C++ for that.  Nevertheless, we should at least have
a consistent definition within the current language structure.

					John Nagle

henry@utzoo.uucp (Henry Spencer) (09/23/89)

In article <13730@well.UUCP> nagle@well.UUCP (John Nagle) writes:
>     I would like to suggest that the time has come to standardize the
>Boolean values in C...

They are already standard.  Integer nonzero means true.  Integer zero
means false.  There is not the slightest hope of changing this now.
Furthermore, it's not clear that it's worth the trouble.
-- 
"Where is D.D. Harriman now,   |     Henry Spencer at U of Toronto Zoology
when we really *need* him?"    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

ian@mva.cs.liv.ac.uk (09/24/89)

In article <1989Sep22.073138.19684@lth.se>, newsuser@lth.se (LTH network news server) writes:
> I completely agree that a boolean data type is needed in C++.  I
> think the definition should define the following properties:
> 
> 	1.  The data type is called "boolean".
>
That's just what _you_ want to call it! Why not call it `bool' or
`logical' or even `int'?

> 	2.  The allowed values are "false" and "true".
>
Why not call them `f' and `t' or `F' and `T' or even `0' and `1'?

> 	3.  int(false) = 0 and int(true) = 1
>
Well, int (0) = 0 and int (1) = 1.

> 	4.  boolean(0) = false, other values are true
>
Wouldn't it be great for conditionals in C to be false if they are testing
integer 0 and to be true if they are testing any other integer? That way
we could use integers instead of a new boolean type. Oh, looks like they
already do that!

Why do we need to introduce a new data type to do the job of a data type
we already have, but in a more complex way?

Ian Finch              Janet: ian@uk.ac.liv.cs.mva
---------              Internet: ian%mva.cs.liv.ac.uk@cunyvm.cuny.edu
                       UUCP: ...mcvax!ukc!ian@uk.ac.liv.cs.mva
===============================================================================
What's a word processor? Well, you know what a food processor does to food ...

rhg@cpsolv.UUCP (Richard H. Gumpertz) (09/24/89)

If the type bool were a new BUILT-IN type then the compiler implementor could
decide what width (and representation values) it should have INDEPENDENTLY
from deciding int, char, etc.  This might result in more efficient
representation on a portable basis.

The casting rules from integral types to bool would no longer catch poor
programmers who write:
        #define bool char
        ...
        int mumble();
        ...
        bool failed;
        failed = mumble();
This fails for 8-bit chars when mumble returns an error code of 0x300.  The
programmer really wanted:
        failed = (mumble() != 0);
or
        failed = (!!mumble());
or
        failed = (mumble() ? true : false);
If type bool were built in, then the (implicit) cast from integral types to
bool would include the "!= 0" test automatically if needed.

Also, the precise representation of bool would now be implementor-defined: it
would only be required that casts of bool to integral types return 0 or 1; the
internal representation of bool might be different.
-- 
==========================================================================
| Richard H. Gumpertz:                        ...uunet!amgraf!cpsolv!rhg |
| Computer Problem Solving, 8905 Mohwak Lane, Leawood, Kansas 66206-1749 |
==========================================================================

wjf@attctc.Dallas.TX.US (Jesse Furqueron) (09/25/89)

In article <13730@well.UUCP>, nagle@well.UUCP (John Nagle) writes:
> 
>      I would like to suggest that the time has come to standardize the
> Boolean values in C.  Most programs have definitions of these, but they
> differ and clash.  As the typing rules become ever tighter, and the number
	
			xyzzy!! and text disappears...

> 
>      I would suggest that the standardized definition be
>      If it's too late to fix this in C, it should be fixed in C++, where
> typing is taken more seriously.
> 
> 					John Nagle


I would suggest rather than FALSE = 0 and TRUE = 1, that the "real" definition
of TRUE is not FALSE (TRUE = not 0), i.e. TRUE = !0.  Therefore the following

#define FALSE	0
#define TRUE	!0 

or for c++ folks

const boolean (FALSE=0, TRUE=!0);

I believe (if this tired and aged memory serves me correctly) that somewhere
K&R refers to this being the evalutations used in if and while statements.


Jesse Furqueron
VISystems
11910 Greeneville Suite 300
LB 29
Dallas, Tx. 75243
(214) 907-8080

-------------------------------------------------------------------------------
As always, the opinions expressed by myself are not necessarily those of my
employer... maybe one of these days they'll learn to listen!!!
-------------------------------------------------------------------------------

dhesi@sun505.UUCP (Rahul Dhesi) (09/25/89)

(The referenced article had a follow-up header of "poster", which I
think is a nasty thing to have done.)

In article <9464@attctc.Dallas.TX.US> wjf@attctc.Dallas.TX.US (Jesse Furqueron)
writes:
>#define FALSE	0
>#define TRUE	!0 

I suggest that defensive programmers eschew these constants because the
temptation to say

     if (x == TRUE) ...

may overcome you some day and you will suffer, unless you can
universally guarantee that you didn't absent-mindedly do something like

     x = isdigit(c);


If, on the other hand, you are willing to either be careful to always
say
     x = (isdigit(c) != 0);

or if you alternatively define

     #define ISTRUE(x)	(x)
     #define ISFALSE(x)	(!(x))

and say

     if (ISTRUE(x)) ...
     if (ISFALSE(y)) ...

instead then the use of TRUE and FALSE is not so dangerous.

Best is just think binary and say:

     x = 0;		/* x is false */
     y = 1;		/* y is true */

and for testing use

     if (x)  ...	/* if x is true */
     if (!y) ...	/* if y is false */

If you really must define a macro, try:

     #define ONE   1
     #define ZERO  0

Now if you see

     if (x == ONE) ...

you immediately realize that this could fail to work.

The problem is that in C any nonzero value is considered to be
true when tested in a boolean context, so

     #define TRUE  1

is misleading.  In a richer language you could perhaps say:

     #define TRUE  [-inf..-1, 1..+inf]

Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

karzes@mfci.UUCP (Tom Karzes) (09/26/89)

In article <9464@attctc.Dallas.TX.US> wjf@attctc.Dallas.TX.US (Jesse Furqueron) writes:
>I would suggest rather than FALSE = 0 and TRUE = 1, that the "real" definition
>of TRUE is not FALSE (TRUE = not 0), i.e. TRUE = !0.  Therefore the following
>
>#define FALSE	0
>#define TRUE	!0 

That's silly.  You should either assume the values that C guarantes:

    #define FALSE 0
    #define TRUE  1

Or else assume nothing and let the compiler figure it out each time:

    #define FALSE (0 != 0)
    #define TRUE  (0 == 0)

Your mistake is that you're confusing C's truth test (!= 0) with its
canonical true and false values (F=0, T=1).  In general, the canonical
true and false values in a language must behave appropriately under its
true test, but there may be non-canonical values which do the same.
In C, there is only one integral false value.  However, there are
also false pointer and floating point types.  In that sense, the "!= 0"
test in itself says nothing about canonical false being an integer zero.

Since they should only be defined once, I think it's a bit extreme to
use the latter definitions shown above, but they do provide the proper
justification for 0 and 1, which are best thought of as constant folded
versions of these (or similar constant expressions which generate canonical
true and false values without depending on what those values are).

karzes@mfci.UUCP (Tom Karzes) (09/26/89)

In article <895@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>(The referenced article had a follow-up header of "poster", which I
>think is a nasty thing to have done.)

I agree.

>I suggest that defensive programmers eschew these constants because the
>temptation to say
>
>     if (x == TRUE) ...
>
>may overcome you some day and you will suffer...

I agree that this sort of thing does happen, particularly in a language
like C which doesn't support a distinct boolean data type but does support
boolean operations defined on integers.  However, I feel that it is primarily
a matter of understanding and engineering discipline.  Proper use of a user
defined boolean data type will only attempt to represent canonical true and
false values in that data type.  It should be sufficient to define:

    typedef int     bool;
    #define FALSE   0
    #define TRUE    1

and to then only use bool to hold TRUE or FALSE (which includes values
generated by comparisons, !, &&, ||, etc.).  Under this usage, the following
constructs should never appear for bool's b, b1, and b2:

        bad form                preferred equivalent
    ----------------            --------------------
    b == FALSE                      ! b
    b != FALSE                      b
    b == TRUE                       b
    b != TRUE                       ! b
    b ? TRUE : FALSE                b
    b ? FALSE : TRUE                ! b
    b1 ? FALSE : b2                 (! b1) && b2
    b1 ? TRUE : b2                  b1 || b2
    b1 ? b2 : FALSE                 b1 && b2
    b1 ? b2 : TRUE                  (! b1) || b2

Expressions of type bool should not be used as integer expression unless
explicitly case to type int, to indicate that the F=0, T=1 behavior is
being assumed.  The need for this shouldn't arise very often (only in
tight little pieces of code where you want to do something like optionally
add 1 to a number, depending on a bool value, and you want it to be really
tight code so you simply add the cast bool, as opposed to "b ? 1 : 0").

garys@bunker.UUCP (Gary M. Samuelson) (09/26/89)

In article <1885@mva.cs.liv.ac.uk> ian@mva.cs.liv.ac.uk writes:

>Wouldn't it be great for conditionals in C to be false if they are testing
>integer 0 and to be true if they are testing any other integer? That way
>we could use integers instead of a new boolean type. Oh, looks like they
>already do that!

In any argument, I find I will tend to take the side opposite that which
is supported largely by ridicule and sarcasm.

>Why do we need to introduce a new data type to do the job of a data type
>we already have, but in a more complex way?

It seems to me that your arguments (such as they are) would apply
equally to "short" and "long" (perhaps even "char").  Why do you think
I should use 32 bits ("int" in some environments) when 1 would do?
I favor the addition of "boolean" to "C" -- it's only logical.

Gary Samuelson

tneff@bfmny0.UU.NET (Tom Neff) (09/26/89)

There is so much code that already thinks it has to - and can - define
what "boolean" is, that adding a reserved "boolean" type would probably
be greeted with more groans than cheers.  Nor does much of this existing
code make any room for 1-bit implementations, from what I've seen.

I think that at MOST, "boolean," "TRUE" and "FALSE" should have the same
status as "NULL," i.e., some (new) standard header like <bool.h> should
define them if you bother to include it.  And the guidance would suggest
saying

	#define boolean int
	#define TRUE 1
	#define FALSE 0

although I have always smiled on clevernesses like

	#define TRUE (1==1)
	#define FALSE (1==0)

-- 
'The Nazis have no sense of humor, so why   -|  Tom Neff
should they want television?' -- Phil Dick  |-  tneff@bfmny0.UU.NET

rhg@cpsolv.UUCP (Richard H. Gumpertz) (09/27/89)

The biggest advantage of a built-in boolean type would be that casts TO it
would test for zero/non-zero rather than just trucating the high-order bits
if sizeof(source) is bigger than sizeof(bool).  Also, (bool)X & (bool)Y would
do "right" thing even if X was 4 and Y was 32.  In other words, & would be
equivalent to && for type bool except that both operands would be evaluated.
-- 
==========================================================================
| Richard H. Gumpertz:                        ...uunet!amgraf!cpsolv!rhg |
| Computer Problem Solving, 8905 Mohwak Lane, Leawood, Kansas 66206-1749 |
==========================================================================

wen-king@cit-vax.Caltech.Edu (King Su) (09/27/89)

In article <7701@bunker.UUCP> garys@bunker.UUCP (Gary M. Samuelson) writes:
<In any argument, I find I will tend to take the side opposite that which
>is supported largely by ridicule and sarcasm.

You shouldn't go around exposing your weakness like that; you can be
manipulated into taking any side.  :-)

>>Why do we need to introduce a new data type to do the job of a data type
<>we already have, but in a more complex way?
>
<It seems to me that your arguments (such as they are) would apply
>equally to "short" and "long" (perhaps even "char").  Why do you think
<I should use 32 bits ("int" in some environments) when 1 would do?
>I favor the addition of "boolean" to "C" -- it's only logical.

It doesn't have to be 32 bits.  Besides, using 32 bits is perfectly OK
if it makes the program faster and if speed is what you are after.  If
space is more important, you can do with 1 bit if you use bit field.
We can do just fine with what we got, so the question is why is boolean
needed and why is it, as you say, logical (perhaps you forgot a smiley).
-- 
/*------------------------------------------------------------------------*\
| Wen-King Su  wen-king@vlsi.caltech.edu  Caltech Corp of Cosmic Engineers |
\*------------------------------------------------------------------------*/

wen-king@cit-vax.Caltech.Edu (King Su) (09/27/89)

In article <393@cpsolv.UUCP> rhg@cpsolv.uucp (Richard H. Gumpertz) writes:
>The biggest advantage of a built-in boolean type would be that casts TO it
<would test for zero/non-zero rather than just trucating the high-order bits
>if sizeof(source) is bigger than sizeof(bool).  Also, (bool)X & (bool)Y would
<do "right" thing even if X was 4 and Y was 32.  In other words, & would be
>equivalent to && for type bool except that both operands would be evaluated.

Why not just do:

#define bool(a) (!!(a))

Then just use bool(X) whenever you wanted to use (bool)X.

-- 
/*------------------------------------------------------------------------*\
| Wen-King Su  wen-king@vlsi.caltech.edu  Caltech Corp of Cosmic Engineers |
\*------------------------------------------------------------------------*/

peter@ficc.uu.net (Peter da Silva) (09/28/89)

Rather than add a boolean type, make bitfeilds more like first-class objects:

typedef int boolean:1;

boolean x;	/* allocates, say, 1 byte */

boolean y, z;	/* allocates a byte each, so you can take an addr */

{
	register boolean a,b,c;	/* Allocates 1 byte for all: no addr needed */
	struct foo { boolean bar, baz; }; /* sizeof(foo) == 1 */
...
-- 
Peter da Silva, *NIX support guy @ Ferranti International Controls Corporation.
Biz: peter@ficc.uu.net, +1 713 274 5180. Fun: peter@sugar.hackercorp.com. `-_-'
"That is not the Usenet tradition, but it's a solidly-entrenched            U
 delusion now." -- brian@ucsd.Edu (Brian Kantor)

foessmei@lan.informatik.tu-muenchen.dbp.de (Reinhard Foessmeier) (09/28/89)

In article <12067@cit-vax.Caltech.Edu> wen-king@cit-vax.UUCP (Wen-King Su) writes:
>...
>It doesn't have to be 32 bits.  Besides, using 32 bits is perfectly OK
>if it makes the program faster and if speed is what you are after.  If
>space is more important, you can do with 1 bit if you use bit field.
>We can do just fine with what we got, so the question is why is boolean
>needed and why is it, as you say, logical (perhaps you forgot a smiley).
>-- 

^Ci tiu diskuto iris tute alian         This discussion has taken a road com-
vojon ol mi komence imagis.  ^Cu        pletely different from what I first
ne unu el la precipaj avanta^goj        imagined.  Wouldn't one of the main
de C-tipo `boolean' estus, ke ^gi       advantages of a `boolean' type in C
ebligus pli striktan kontrolon de       be the possibility for stricter type
tipoj (pli ol la ^sparo de kelkaj       checking (rather than saving a few
bitoj)?  Kompreneble, tiuj belaj        bits)?  Of course, such beloved con-
konstrua^joj "x<y<z<u" tiam ne          structs as "x<y<z<u" would no longer
estus eblaj, se ne permesi ankaw        be possible, unless comparison of
komparon de bule-oj.                    `boolean's would be permitted.

>/*------------------------------------------------------------------------*\
>| Wen-King Su  wen-king@vlsi.caltech.edu  Caltech Corp of Cosmic Engineers |
>\*------------------------------------------------------------------------*/
__________
Reinhard F\"ossmeier, Technische Univ. M\"unchen | UNOX is a trademark of
foessmeier@infovax.informatik.tu-muenchen.dbp.de |     "Union Deutsche 
   [ { relay.cs.net | unido.uucp } ]             | Lebensmittelwerke GmbH"

pl@etana.tut.fi (Lehtinen Pertti) (09/28/89)

From article <12070@cit-vax.Caltech.Edu>, by wen-king@cit-vax.Caltech.Edu (King Su):
> 
> #define bool(a) (!!(a))
> 
> Then just use bool(X) whenever you wanted to use (bool)X.
> 

	Then suddenly just behind the corner cames C-compiler from
	ACME-corporation and realizes '!!a' -> negation of negation is
	same as original -> we can optimize it away.

	Nice, isn't it.  And too real too.

--
pl@tut.fi				! All opinions expressed above are
Pertti Lehtinen				! purely offending and in subject
Tampere University of Technology	! to change without any further
Software Systems Laboratory		! notice

quiroz@cs.rochester.edu (Cesar Quiroz) (09/28/89)

In <8862@etana.tut.fi>, pl@etana.tut.fi (Lehtinen Pertti) suggested
that the bogus "optimization"
| 	Then suddenly just behind the corner cames C-compiler from
| 	ACME-corporation and realizes '!!a' -> negation of negation is
| 	same as original -> we can optimize it away.
could make !!a be just good old a, instead of guaranteed 0 or 1.

Either such compiler exists, in whose case it is broken and we
should not lose much sleep over it, or it doesn't.  My impression is
that it doesn't, barring better information from the poster.   That
would be a really poor case of arguing from the incompetence of a
non-existent compiler.  Madness lies that way; opposing or
supporting something just because some compiler could, perhaps,
maybe, if we try hard enough, screw up the language is ridiculous.

If you know of a compiler that makes that mistake, expose it to the
community, that may get it fixed (or at least may make it reasonable
to be extra cautious when having to use the critter).  Else, please
don't invent it just for the sake of argument.
-- 
                                      Cesar Augusto Quiroz Gonzalez
                                      Department of Computer Science
                                      University of Rochester
                                      Rochester,  NY 14627

jeenglis@nunki.usc.edu (Joe English) (09/29/89)

pl@etana.tut.fi (Lehtinen Pertti) writes:
>From article <12070@cit-vax.Caltech.Edu>, by wen-king@cit-vax.Caltech.Edu (King Su):
>> #define bool(a) (!!(a))
>> 
>> Then just use bool(X) whenever you wanted to use (bool)X.
>	Then suddenly just behind the corner cames C-compiler from
>	ACME-corporation and realizes '!!a' -> negation of negation is
>	same as original -> we can optimize it away.

But that won't happen with a working compiler, since
!!a is not equivalent to a.

This macro doesn't solve the perceived problem,
though:  what is wanted is a first-class boolean type
(don't ask me what it was wanted *for*, I don't
know...) This solution requires explicit casting of
every boolean expression.

--Joe English

  jeenglis@nunki.usc.edu.

tim@cayman.amd.com (Tim Olson) (09/29/89)

In article <8862@etana.tut.fi> pl@etana.tut.fi (Lehtinen Pertti) writes:
| From article <12070@cit-vax.Caltech.Edu>, by wen-king@cit-vax.Caltech.Edu (King Su):
| > 
| > #define bool(a) (!!(a))
| > 
| > Then just use bool(X) whenever you wanted to use (bool)X.
| > 
| 
| 	Then suddenly just behind the corner cames C-compiler from
| 	ACME-corporation and realizes '!!a' -> negation of negation is
| 	same as original -> we can optimize it away.
| 
| 	Nice, isn't it.  And too real too.

And wrong, too.  Do you know of a compiler that does this in the
general case?

	-- Tim Olson
	Advanced Micro Devices
	(tim@amd.com)

gwyn@smoke.BRL.MIL (Doug Gwyn) (09/29/89)

In article <8862@etana.tut.fi> pl@etana.tut.fi (Lehtinen Pertti) writes:
-	Then suddenly just behind the corner cames C-compiler from
-	ACME-corporation and realizes '!!a' -> negation of negation is
-	same as original -> we can optimize it away.

The point is, it isn't a no-op.
If ACME delivers a non-conforming implementation,
you should hold them to your specification that requires Standard
conformance.

diamond@csl.sony.co.jp (Norman Diamond) (09/29/89)

From article <12070@cit-vax.Caltech.Edu>, by wen-king@cit-vax.Caltech.Edu (King Su):

>> #define bool(a) (!!(a))
>> Then just use bool(X) whenever you wanted to use (bool)X.

In article <8862@etana.tut.fi> pl@etana.tut.fi (Lehtinen Pertti) writes:

>	Then suddenly just behind the corner comes C-compiler from
>	ACME-corporation and realizes '!!a' -> negation of negation is
>	same as original -> we can optimize it away.

Actually no.  If the optimizer reduces this to a no-op without knowing
that "a" must already be 0 or 1, then the optimizer is broken.  "!"
was required to produce a result of 0 or 1 even before K&R-1.

-- 
Norman Diamond, Sony Corporation (diamond@ws.sony.junet)
  The above opinions are inherited by your machine's init process (pid 1),
  after being disowned and orphaned.  However, if you see this at Waterloo or
  Anterior, then their administrators must have approved of these opinions.

condict@cs.vu.nl (Michael Condict) (09/29/89)

In article <12070@cit-vax.Caltech.Edu> wen-king@cit-vax.UUCP (Wen-King Su) writes:
>In article <393@cpsolv.UUCP> rhg@cpsolv.uucp (Richard H. Gumpertz) writes:
>>The biggest advantage of a built-in boolean type would be that casts TO it
><would test for zero/non-zero rather than just trucating the high-order bits
>>if sizeof(source) is bigger than sizeof(bool).  Also,  . . .
>
>Why not just do:
>
>#define bool(a) (!!(a))
>
>Then just use bool(X) whenever you wanted to use (bool)X.
>

Because neither lint nor the C compiler will help you find the places where
you forgot to use bool(X).  Presumably, ints would be cast to the proposed
Boolean type automatically, as needed.  Or the two types would be incompatible
and require an explicit cast to avoid an error message (except when ints are
used in the bool-expr of a while loop or if statement).

One of the biggest problems with C, compared to strongly typed languages
like Pascal, is that it doesn't help you enough in finding type mismatch
errors.  ANSI C does not solve this problem completely, although its
function prototypes at least allow compilers to do their weak type checking
across function boundaries, as well as within a single compilation unit.
Unfortunately the only cases for which the weak type checking produces error
messages is when pointers and numeric types, or two different pointer types,
are mixed.

Consider the case where you have a function that expects a float, an int and
a char.  In most cases, you the programmer consider these to be different,
incompatible types, and would consider it an error to pass a character
constant in the place where the float is expected.  This would almost cer-
tainly indicate that the caller got the order of the parameters wrong.
C, on the other hand, happily (and quietly) converts the character, which
is a numeric type, to a float, in the presence of a prototype.  In the absence
of a prototype, lint will complain about the mismatch of the char and float,
but will not complain if you get the order of the char and int parameter
wrong.

The issue is this: is a programming language always more powerful when it
accepts a given construct, rather than rejecting it with an error message?
Or is it sometimes weaker?  Opinions differ when specific constructs are
discussed, but I doubt if anyone would want to go back to the bad old
days when integers and pointers were compatible types and could be
interchanged freely.

Michael Condict    condict@cs.vu.nl
Vrije University

bright@Data-IO.COM (Walter Bright) (09/30/89)

In article <8862@etana.tut.fi> pl@etana.tut.fi (Lehtinen Pertti) writes:
<From article <12070@cit-vax.Caltech.Edu>, by wen-king@cit-vax.Caltech.Edu (King Su):
<< #define bool(a) (!!(a))
<	Then suddenly just behind the corner cames C-compiler from
<	ACME-corporation and realizes '!!a' -< negation of negation is
<	same as original -< we can optimize it away.
If a compiler thought that (!!a) == (a), then it is a compiler bug.
<	Nice, isn't it.  And too real too.
If you run up against such wretchedness, you can do this:

#if ACME_C
#define bool(a)	((a) != 0)	/* if desperate try ((a)?1:0)	*/
#else
#define bool(a) (!!(a))
#endif

I have a copy of K&R which I believe is a first printing. It *clearly*
states that ! is to return 1 or 0. Not -1. Not implementation defined.
Using ! is portable. If it doesn't work with your C, treat it like any
other compiler bug.

If anyone knows of a *current* C compiler that has a problem with this,
please email me. I'm curious!