Topic: The lack of an explicit boolean type (was Your opinions please)


Author: deef@techbook.techbook.com (Derek Foster)
Date: 13 Jul 1993 11:05:45 -0700
Raw View
jamshid@emx.cc.utexas.edu (Jamshid Afshar) writes:

>In article <C9q48M.8vK@syacus.acus.oz.au> ian@syacus.acus.oz.au (Ian Joyner) writes:
>|grumpy@cbnewse.cb.att.com (Paul J Lucas) writes:
>|> Any competent C/C++ programmer will know that 0 === false and
>|> non-0 === true.  If someone doesn't know that, s/he has no
>|> business reaidng C/C++ code.
>|
>|But a whole generation of programmers have had their thought processes
>|perverted by this. A good language will force no such assumptions of
>|underlying machine level values on the programmer. This must be the simplest
>|of abstractions, but C gets it wrong.

>                                                       C/C++ doesn't
>have a "real" boolean type; never had it, never will.  You'll quickly
>get used to it; you might even come to like it.

I may get used to it; I don't think I'll ever like it.

>                                                  I don't think C's
>Lack of a boolean type has caused me psychological damage or impaired
>my ability to design software.

Perhaps, but it may cause psychological damage to others who try to
understand the software which you write. I recently worked on a project
in which the programmer used 'int' for boolean values. He also sometimes
returned #defines such as FALSE and TRUE from functions which were allowed
to return arbitrary integers as well. (some functions could return TRUE,
FALSE, or ERROR, for instance.)

This meant that when I noticed a function returning a constant such as TRUE,
I still was not allowed to assume that if (x != FALSE) then (x == TRUE).
Finally, in frustration, I rewrote the entire mess to use my own 'bool'
type, thus explicitly documenting whether each function expected/returned a
binary value, an integral value, or a three-state value. I also made sure
that when a function returned a binary value, the value was either 1 or 0.
Previously, some functions contained code like 'return x & SOME_FLAG;' and
were then used in contexts like 'if (somefunction()) dosomething()' which
made it not at all obvious that although somefunction() returned a boolean
value, it was not guaranteed to be 1 or 0, thus making code like 'if
(functiona()==functionb())' bomb.

Once I made these changes, readability was IMMENSELY improved. Nonetheless,
because the language doesn't define a boolean type, programmers are (1) not
encouraged to use it, sacrificing readability, and (2) if they implement it
themselves, they will disagree with each other on exactly how it should be
implemented. I have a 'typedef unsigned char bool;' but I know other people
use 'typedef int boolean', etc. What happens when we try to merge libraries?

The problem becomes even more severe when we go to C++, since we now have
the confusion between (int)0, (void *)0, and (boolean)0. Why on earth does
the standard iostream class have an operator void *? Not because they
actually intend to cast anything to a void *, but because they want to
allow an iostream in expressions like:

   if (cin) ...

and they don't want people to be able to do things like

   int x = cin+1;

(which would have been possible if operator int had been used instead.) Yet,
to a casual programmer looking at a header file, there is absolutely no clue
that this void * is intended to represent a boolean value. They had to do it
this way because there was no standard way they could declare an operator
bool, which is what they really meant. If there was a standard boolean type,
and the language was changed to support it, I could distinguish between, for
instance,

String x;
if (x) ...  // calls x.operator bool
if (x != "abc") ... // calls x.operator char *

whereas now, for instance, we have
if (somefunc(FALSE))  // calls somefunc(int)? somefunc(char *)? what?

I think that a boolean type could be added to the language definition
fairly painlessly without breaking much code (I am tempted to say 'any code'
because I can't think of anything that would break, but I suppose there
probably is something. In many cases, I think that programmers could simply
remove their own boolean types and substitute in the new one from the
language definition.) 'enum' types almost do the job, except that one would
have to put casts into places such as
  enum bool {FALSE=0,TRUE=1};
  bool y = (bool)(x > 3);   // need a cast here. VERY annoying.

I would LOVE the ability to overload based on boolean types, and more
predictable behavior from other programmers along the lines of:
  operator int(bool x) {return x?1:0;}  // default casting rules
  operator bool(int x) {return x>0?TRUE:FALSE}
  bool operator ==(int x, int y);      // default operator definitions
  bool operator ||(bool x, bool y);
  int operator | (int x, int y);
  if (bool) { ... }       // how the compiler sees these constructs
  while (bool) { ... }
  etc.

There are even perhaps some optimization opportunities due
to this, since the compiler could make optimizations such as

bool x;

old code:
if (x==TRUE) do_something1();
something_else();
if (x==FALSE) do_something2();

new code:
if (x) {do_something1(); something_else();}
else   {something_else(); do_something2();}

In addition, a particular compiler would be able to optimize its code
so that a bool type occupied as many bits as was efficient for the
target machine (probably equivalent to an int or char in most cases),
which might speed parameter passing and other data movement. The current
use by most programmers of 'int' for boolean information prevents such
optimizations, causing programs to waste time passing entire ints around
when passing single characters might do just as well. One might even
hypothesize a machine optimizing several bool variables into one machine
word, although I don't consider that likely.

I am rather puzzled as to why so many people seem to fervently object to
the introduction of a standard boolean type to c++. It seems like a rather
safe extension that would provide benefits all around. It could even be
disabled via a compiler option if necessary for dealing with old code.

>Jamshid Afshar
>jamshid@emx.cc.utexas.edu

Derek Riippa Foster
--
deef@techbook.COM  Public Access User --- Not affiliated with TECHbooks
Public Access UNIX and Internet at (503) 220-0636 (1200/2400, N81)




Author: mccall@mksol.dseg.ti.com (fred j mccall 575-3539)
Date: Thu, 15 Jul 1993 17:41:06 GMT
Raw View
In <21uthp$5in@techbook.techbook.com> deef@techbook.techbook.com (Derek Foster) writes:

>jamshid@emx.cc.utexas.edu (Jamshid Afshar) writes:

>>In article <C9q48M.8vK@syacus.acus.oz.au> ian@syacus.acus.oz.au (Ian Joyner) writes:

>>                                                       C/C++ doesn't
>>have a "real" boolean type; never had it, never will.  You'll quickly
>>get used to it; you might even come to like it.

>I may get used to it; I don't think I'll ever like it.

Then may I suggest a different choice of language?

>>                                                  I don't think C's
>>Lack of a boolean type has caused me psychological damage or impaired
>>my ability to design software.

>Perhaps, but it may cause psychological damage to others who try to
>understand the software which you write. I recently worked on a project
>in which the programmer used 'int' for boolean values. He also sometimes
>returned #defines such as FALSE and TRUE from functions which were allowed
>to return arbitrary integers as well. (some functions could return TRUE,
>FALSE, or ERROR, for instance.)

As long as he's consistent this shouldn't be a problem.

>This meant that when I noticed a function returning a constant such as TRUE,
>I still was not allowed to assume that if (x != FALSE) then (x == TRUE).
>Finally, in frustration, I rewrote the entire mess to use my own 'bool'
>type, thus explicitly documenting whether each function expected/returned a
>binary value, an integral value, or a three-state value. I also made sure
>that when a function returned a binary value, the value was either 1 or 0.

And for all this work you gained ... ?

>Previously, some functions contained code like 'return x & SOME_FLAG;' and
>were then used in contexts like 'if (somefunction()) dosomething()' which
>made it not at all obvious that although somefunction() returned a boolean
>value, it was not guaranteed to be 1 or 0, thus making code like 'if
>(functiona()==functionb())' bomb.

That code should never have been written that way in the situation you
describe.  Did the original author write it that way, or did someone
add that later who didn't know C and didn't bother to check what those
functions could return?

>Once I made these changes, readability was IMMENSELY improved.

For you.

>Nonetheless,
>because the language doesn't define a boolean type, programmers are (1) not
>encouraged to use it, sacrificing readability,

By you.  C/C++ programmers would be able to read it just fine.

>and (2) if they implement it
>themselves, they will disagree with each other on exactly how it should be
>implemented. I have a 'typedef unsigned char bool;' but I know other people
>use 'typedef int boolean', etc. What happens when we try to merge libraries?

You will find that both libraries were written by people who were
trying to bend the language to suit themselves rather than working
*with* it, the way they should have been.

>I think that a boolean type could be added to the language definition
>fairly painlessly without breaking much code (I am tempted to say 'any code'
>because I can't think of anything that would break, but I suppose there
>probably is something.

Like all the code that checks for 'boolean' functions to return things
like 0 for false rather than your 'new false'?

>I would LOVE the ability to overload based on boolean types, and more

But the question isn't what *you* would love -- it's what everyone
else using the language would 'love'.  I think a large number of us
like things the way they are.

>There are even perhaps some optimization opportunities due
>to this, since the compiler could make optimizations such as

>bool x;

>old code:
>if (x==TRUE) do_something1();
>something_else();
>if (x==FALSE) do_something2();
>
>new code:
>if (x) {do_something1(); something_else();}
>else   {something_else(); do_something2();}

You need a boolean type for this?  They both look like legal code to
me, and I generally write stuff that looks like the second one -- and
all without a boolean type.

>I am rather puzzled as to why so many people seem to fervently object to
>the introduction of a standard boolean type to c++. It seems like a rather
>safe extension that would provide benefits all around. It could even be
>disabled via a compiler option if necessary for dealing with old code.

Because it breaks existing code and provides nothing in return.

--
"Insisting on perfect safety is for people who don't have the balls to live
 in the real world."   -- Mary Shafer, NASA Ames Dryden
------------------------------------------------------------------------------
Fred.McCall@dseg.ti.com - I don't speak for others and they don't speak for me.




Author: jimad@microsoft.com (Jim Adcock)
Date: 16 Jul 93 17:52:21 GMT
Raw View
In article <21uthp$5in@techbook.techbook.com> deef@techbook.techbook.com (Derek Foster) writes:
|I am rather puzzled as to why so many people seem to fervently object to
|the introduction of a standard boolean type to c++. It seems like a rather
|safe extension that would provide benefits all around. It could even be
|disabled via a compiler option if necessary for dealing with old code.

My argument would be that if you (or anyone) were to at this point in
time add a bool type to C++, while remaining compatible with the long
established goals of C++, then you will end up with a bool type which
is so weak as to not be worth the effort.

First, note that as soon as you start talking compiler switches or
pragmas, then you are not talking *ONE* language, rather you are talking
*MANY* languages.  The goal of the language standardization effort is
to come up with *ONE* definition of the language that implementors
can create compiler for, and motivated programmers can write code to.

Further, a long time high priority goal of C++ has been to avoid breaking
existing C and C++ code, and if you do have to break it, make those breaks
the rare exception rather than the rule.

So, if we are to avoid breaking existing code in lots of places, what
properties would a "bool" type have?

a) It would have to support *implicit* conversion *from* int, because that
idiom is common in existing programs:

 bool b = (i1 || i2);  // false if both ints zero

b) It would have to support *implicit* conversion *from* pointers, because that
idiom is common in existing programs:

 bool b = !ptr; // true if the ptr is null

c) It would have to support *implicit* conversion *to* int, because that
idiom is common in existing programs:

 int nullcnt = !p1 + !p2 + !p3; // sum of three bools

d) How many bits of storage should a bool require?  By the basic rules
of the language, it must occupy at least one byte, but you're going to
break a ton of code if you make it occupy anything other than the
identical size as an int.  Further, using other than an int implies
a change in the speed/size tradeoffs programs use, so you'd be breaking
the implementation intent of a lot of programs.

e) What are you going to call this thing?  Better not choose any of the
common names, because tons of programs already use the common names to
mean things different than your intent, indeed the common complaint is
that differing programs can't agree on "the" correct definition of "bool".
So better not call it BOOL, bool, Bool, boolean, BOOLEAN, .... nor
call its truth values TRUE, FALSE, true, false, True, False, Set, Clear,
set clear.... or any other "pretty" names because such have all been
used in programs many times before -- and with different meaning than
you or I would consider "sane".

f) Finally, even if *you* know how *you* want to answer all these questions,
then explain to me how *you* are going to convince the rest of the world
that they should follow *your* recommendations, and further to change
their existing programs to be compatible with *your* ideas?  And if *you*
can't convince everyone else to follow your ideas, then what are your
choices?  *You* can invent your own incompatible "bool" type, using
existing capabilities of the language, such as the new enums as distinct
types, or alternately *you* can attempt to modify *your* programming
styles and desires to best fit in with the existing bulk of C/C++ code
already out there.

I don't think people disagree that *conceptually* a bool type in C++
would be a nice thing to have.  Its just that many people realize
that such is not reasonably possible today, given the bulk of C/C++
history.  If you wanted to invent a new totally incompatible language
from scratch, you could do a lot of things differently than C/C++
does them already.  But then, there are a ton of these totally incompatible
languages out there already -- check them out, and see what you think.
Most people do check them out -- and then decide maybe the C/C++ compromises
are something they can live with after all.




Author: schlein@umbc.edu (Jonas Schlein)
Date: 17 Jul 1993 15:21:03 -0400
Raw View
[long post deleted]

Sadly to say, but you are right...

The old 'typedef int bool' is probably best since it provides the reader with
the knowledge that a boolean is being returned at quick glance yet it will
be compatible with all code that uses just int as a return value.

Personally when I quickly glance at a function that returns int my first
thought is that some calculation is being done which is not the case when
just a TRUE or FALSE false is really the intention.

Just syntactic sugar...
--
With all the frowning going on I guess some |  Jonas Schlein
people's faces just stuck in that position? |  schlein@umbc8.umbc.edu




Author: whitney@christie.Meakins.McGill.CA (Whitney de Vries)
Date: Sat, 17 Jul 1993 20:47:34 GMT
Raw View
: The old 'typedef int bool' is probably best ..

As much as I prefer other languages to C/C++ because
they have booleans ( amoung other things ) I don't think
that using #defines or typedefs is the way to go. Sooner
or later you will end up with code where one person uses
it one way and another person ( hopefully not the first
person :-) ) uses it another way and you end up with some
sort of conflict.

In short with C/C++ use int if what you want is BOOLEAN.

Whitney




Author: schlein@umbc.edu (Jonas Schlein)
Date: 17 Jul 1993 21:42:13 -0400
Raw View
> In short with C/C++ use int if what you want is BOOLEAN.

Obviously the most portable, but not the best and not the most understandable
way to go.
--
With all the frowning going on I guess some |  Jonas Schlein
people's faces just stuck in that position? |  schlein@umbc8.umbc.edu




Author: jfc@athena.mit.edu (John F Carr)
Date: 18 Jul 1993 09:21:11 GMT
Raw View
In article <1993Jul17.204734.5000@sifon.cc.mcgill.ca>
 whitney@christie.Meakins.McGill.CA (Whitney de Vries) writes:

>Sooner or later you will end up with code where one person uses
>it one way and another person ( hopefully not the first
>person :-) ) uses it another way and you end up with some
>sort of conflict.

Sooner.  Much sooner.  I had to fight with conflicting definitions of boolean
types a few years ago, I think when I was porting X code to AIX 1.2.  Both
conflicting definitions were in header files that weren't supposed to be
modified.

--
    John Carr (jfc@athena.mit.edu)




Author: nagle@netcom.com (John Nagle)
Date: Sun, 18 Jul 1993 18:46:53 GMT
Raw View
jimad@microsoft.com (Jim Adcock) writes:
>So, if we are to avoid breaking existing code in lots of places, what
>properties would a "bool" type have?

     Here's a compatible possiblity:

EXTENSION

 A new type, type "boole" is defined.  "boole" has two values,
"true" and "false".  All relational operators return results of type
"boole".  "If" and "?" expect an argument of type "boole".  A value
of type "boole" requires at least one bit of space.  The logical operators
"&&" and "||" return results of type "boole".

BACKWARDS COMPATIBILITY FEATURES

       Implicit conversion from "int" to "boole" is defined.
  b = (i != 0)

       Implicit conversion from "boole" to "int is defined".
  i = (b ? 1 : 0)

       Implicit conversion to "boole" of any type convertable to "int" is
       defined as a conversion to "int", then "boole".

       Implicit conversion from "boole" to any type convertable from "int"
       is defined as a conversion to "int", then the desired type.

       TRUE is predefined as equal to "true".  FALSE is predefined
       as equal to "false".  Attempts to redefine "true" or "TRUE"
       as 1 or "false" or "FALSE" as 0 will not be considered errors,
       and may generate obsolete-construct warnings.  This includes
       definition as constants of an "enum".

       The arithmetic operators, if applied to "boole" operands,
       imply conversion to "int".

DISCUSSION

       This meets most of the criteria Jim Adcock lays down.  The name
"boole" is rare enough so as not to break much, if any, code, and any
impact will be clearly detected at compile time.  The usage of "true"
and "false" is upward compatible, solving the biggest problem.  The C idiom
of testing for nonzero values in an "if" statement is preserved.
Existing programs that don't use "boole" at all will continue to work.

       Most of the conversions called for above don't actually generate
any code, so there isn't an efficiency penalty.

       The only major problem is the size of a "boole".  Adcock says
"but you're going to break a ton of code if you make it occupy anything
other than the identical size as an int."  I'd like to see more
information on this.  This is an issue in compatibility with existing
structures, of course, but since those structures won't be defined with
"boole", existing programs will continue to work.

       There are some rare programs that will break.  Defining
"TRUE" as 0 and "FALSE" as -1 is used in a few programs.  Such programs
will not compile until fixed.

       In exchange for such fixes, it becomes possible to combine
libraries from different sources without clashes on the definition of
"boolean", changing only any "typedef boolean int" or "typedef boolean
char" to "typedef boolean boole".

       Comments?

     John Nagle






Author: karl@dme3.osf.org (Karl Heuer)
Date: 18 Jul 1993 23:00:36 GMT
Raw View
In article <1993Jul16.175221.8662@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>My argument would be that if you (or anyone) were to at this point in
>time add a bool type to C++, while remaining compatible with the long
>established goals of C++, then you will end up with a bool type which
>is so weak as to not be worth the effort.  [Because bool would have to
>automatically convert to/from int, for compatibility with existing code.]

My preference would be to create a <bool.h> which defines symbols for the
new type and for the two constants, and have the standard assert that "strong
booleans" (i.e. *no* automatic conversions to/from ints!) are in effect
whenever this header has been included.  (Yes, I'll admit that this is just a
pragma in disguise.)

As a second choice, I'd settle for saying that the implementation shall
provide <bool.h>, and that certain forms of strong typechecking *may* be
enabled by it.  This way existing implementations could conform simply by
providing a typedef and two #defines (and not providing "strong booleans"),
and probably some vendors would choose to provide the whole thing, in order
to improve optimization and compile-time checking.

As a third choice, I'd settle for just the existence of <bool.h>, so that
the type and constants would have standard names, thus avoiding the collisions
that people have been griping about.

Btw, if I were designing the language from scratch, with no compatibility
issues, I'd fix "char" and "enum" as well as "bool".  Hmm, maybe I should
amend my proposal to <strongtypes.h>, and get all three at once.  And maybe
fix the null pointer constant, while I'm at it.

Oh well.  I'm clearly dreaming now.

Karl W. Z. Heuer (karl@osf.org), The Walking Lint




Author: ampe@cbnews.cb.att.com (john.e.ampe)
Date: Mon, 19 Jul 1993 16:28:26 GMT
Raw View
In article <nagleCADIu5.LMI@netcom.com> nagle@netcom.com (John Nagle) writes:
>jimad@microsoft.com (Jim Adcock) writes:
>EXTENSION
>
> A new type, type "boole" is defined.  "boole" has two values,
>"true" and "false".  All relational operators return results of type
>"boole".  "If" and "?" expect an argument of type "boole".  A value
>of type "boole" requires at least one bit of space.  The logical operators
>"&&" and "||" return results of type "boole".
>
>BACKWARDS COMPATIBILITY FEATURES
>
>       Implicit conversion from "int" to "boole" is defined.
>  b = (i != 0)

Since you have stated that relational operators return "boole,"
I don't see a conversion here.

>       Implicit conversion from "boole" to "int is defined".
>  i = (b ? 1 : 0)

Likewise.

One problem associated with a boolean type that I have not seen
mentioned is efficiency.  C programers are used to having "if (i)"
translated into a single test instruction (assuming "i" is already in
a register).  However, with the above definitions, I would expect
cfront to translate "if (i)" to "if (i? 1: 0)".  A good optimizer
would remove the extra test here, but will it be possible in all
cases?  Are efficiency-minded programmers willing to take the risk?

John_Ampe@att.com




Author: dhesi@rahul.net (Rahul Dhesi)
Date: Mon, 19 Jul 1993 17:47:49 GMT
Raw View
In <21uthp$5in@techbook.techbook.com> deef@techbook.techbook.com (Derek
Foster) writes:

>This meant that when I noticed a function returning a constant such as TRUE,
>I still was not allowed to assume that if (x != FALSE) then (x == TRUE).

I read the rest of this thread, and frankly, I still don't know just
what the problem is and why it needs to be solved.  In both C and C++,
booleans are handled as follows:

     - conditionals return 0 or 1
     - tests interpret 0 as false and anything else as true

So if a function returns 0, it may be interpreted as a false result,
and any other result may be interpreted as true.  In the quoted
example, apparently the programmer wanted the function to return three
results:  truel, false, and something_else.  This is highly unusual,
but still usable:

   i = myfunc();
   if (i == 0)
      /* ... must be false ... */
   else if (i == something_else)
      /* ... must be something_else ... */
   else
      /* ... must be true ... */

However, defining constants like TRUE and FALSE is unwise.  As I have
often said, if you MUST define symbols for true and false, please do it
thus:

   #define ZERO 0
   #define ONE  1

Now this may seem silly, but look at the code:

   i = myfunc();
   if (i == ZERO)
      /* ... must be false ... */
   else if (i == ONE)
      /* ... must be 1, or true ... */
   else
      /* ... must be true -- neither 1 nor 0, so some other nonzero value ... */

using ONE and ZERO immediately tells you not to assume that
(i != ZERO) implies (i == ONE).  Using TRUE and FALSE is misleading.

The correct -- and impractical -- solution is to redefine the languge
to allow the following defines:

   #define FALSE  0
   #define TRUE   [-inf .. -1, 1 .. inf]

Now in this more powerful language we can assume that (i != FALSE)
implies (i == TRUE), where equality with TRUE is defined the same way
as set membership.

But C and C++ aren't rich enough to allow this, so let's just stick
with 0 and 1, or ZERO and ONE if you prefer.

If you MUST define TRUE and FALSE, they should be tested with these
macros:

   #define istrue(i) ((i) != 0)
   #define isfalse(i) ((i) == 0)

Now !istrue(i) does imply isfalse(i), so we're back to a clean
boolean approach.
--
Rahul Dhesi <dhesi@rahul.net>
also:  dhesi@cirrus.com




Author: karl@dme3.osf.org (Karl Heuer)
Date: 19 Jul 1993 18:59:09 GMT
Raw View
In article <CAF73o.G6w@cbnews.cb.att.com> ampe@cbnews.cb.att.com (john.e.ampe) writes:
>One problem associated with a boolean type that I have not seen
>mentioned is efficiency.  C programers are used to having "if (i)"
>translated into a single test instruction (assuming "i" is already in
>a register).  However, with the above definitions, I would expect
>cfront to translate "if (i)" to "if (i? 1: 0)".

You've got the conversion backwards.  Assuming "i" is an int, and "if" is
redefined to expect a boolean operand, then cfront would apply the i-to-b
conversion and emit "if (i != 0)".  Since  this is just making explicit a step
that the C compiler already has to do anyway, it should generate exactly the
same code.




Author: mccall@mksol.dseg.ti.com (fred j mccall 575-3539)
Date: Mon, 19 Jul 1993 21:40:35 GMT
Raw View
In <22a9plINN2dn@umbc8.umbc.edu> schlein@umbc.edu (Jonas Schlein) writes:

>> In short with C/C++ use int if what you want is BOOLEAN.

>Obviously the most portable, but not the best and not the most understandable
>way to go.

It is if the people reading your code are C/C++ programmers.  If they
are not, of course, you should probably not be trying to write code
that is readable to them in the first place.  Rather like insisting
that 'readable English' is that which a monolingual Frenchman could
read and understand.

--
"Insisting on perfect safety is for people who don't have the balls to live
 in the real world."   -- Mary Shafer, NASA Ames Dryden
------------------------------------------------------------------------------
Fred.McCall@dseg.ti.com - I don't speak for others and they don't speak for me.




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Tue, 20 Jul 1993 05:32:52 GMT
Raw View
ampe@cbnews.cb.att.com (john.e.ampe) writes:

>One problem associated with a boolean type that I have not seen
>mentioned is efficiency.

I've seen a lot of red herrings in this debate, but this one would have
to take the cake (to mix my metaphors :-)
Any half-decent optimizer will produce just as efficient code with a boolean
type as would be produced without one. Indeed by providing a boolean
type you give the compiler additional information which can be used to
*improve* optimization. For example, I think the Borland Pascal compiler
puts boolean function return values in one of the CPU's status flags
rather than in a register. This can't be done in C without relatively difficult
global analysis.

>C programers are used to having "if (i)"
>translated into a single test instruction (assuming "i" is already in
>a register).  However, with the above definitions, I would expect
>cfront to translate "if (i)" to "if (i? 1: 0)".  >A good optimizer
>would remove the extra test here, but will it be possible in all
>cases?

In all cases where the language would require booleans to be used, yes,
it would be easy to eliminate. (In 'if', 'while', and 'for' statements.)

For function return values or variables which are explicitly declared
as type 'boole', then extra tests might be required when converting
from an integer to a boole. But this only happens if the programmer
declares things as having type boole, it would not be introduced behind
the programmers back. And furthermore, these 'extra' tests might
not be 'extra' at all - if the variable / function return value is stored
in a status flag, the test would not be 'extra'. Storing a boolean in a
status flag frees an extra register for other variables, and means that
 if (cond)
can become a single conditional branch instruction rather than a
test instruction followed by a conditional branch.

(Of course not all CPUs have test instructions and a condition code register,
so this sort of optimization is not universally applicable.)

>Are efficiency-minded programmers willing to take the risk?

Efficiency-minded programmers use compilers with decent optimizers.

--
Fergus Henderson                     fjh@munta.cs.mu.OZ.AU




Author: hopps@yellow.mmm.com (Kevin J Hopps)
Date: Tue, 20 Jul 93 19:58:31 GMT
Raw View
dhesi@rahul.net (Rahul Dhesi) writes:

>In <21uthp$5in@techbook.techbook.com> deef@techbook.techbook.com (Derek
>Foster) writes:

>>This meant that when I noticed a function returning a constant such as TRUE,
>>I still was not allowed to assume that if (x != FALSE) then (x == TRUE).

>I read the rest of this thread, and frankly, I still don't know just
>what the problem is and why it needs to be solved.  In both C and C++,
>booleans are handled as follows:

>     - conditionals return 0 or 1
>     - tests interpret 0 as false and anything else as true

>So if a function returns 0, it may be interpreted as a false result,
>and any other result may be interpreted as true.  In the quoted
>example, apparently the programmer wanted the function to return three
>results:  truel, false, and something_else.  This is highly unusual,
>but still usable:

>   i = myfunc();
>   if (i == 0)
>      /* ... must be false ... */
>   else if (i == something_else)
>      /* ... must be something_else ... */
>   else
>      /* ... must be true ... */

>However, defining constants like TRUE and FALSE is unwise.  As I have
>often said, if you MUST define symbols for true and false, please do it
>thus:

Defining the constants is not unwise.  Using them unwisely is unwise.

>   #define ZERO 0
>   #define ONE  1

Are you serious?

>Now this may seem silly,

You're right.

>                         but look at the code:

>   i = myfunc();
>   if (i == ZERO)
>      /* ... must be false ... */
>   else if (i == ONE)
>      /* ... must be 1, or true ... */
>   else
>      /* ... must be true -- neither 1 nor 0, so some other nonzero value ... */

>using ONE and ZERO immediately tells you not to assume that
>(i != ZERO) implies (i == ONE).  Using TRUE and FALSE is misleading.

Seeing the use of ONE and ZERO is more likely to tell me to rewrite the
code.  Using TRUE and FALSE is only misleading if it is used improperly,
such as in tests.  As another netter so correctly pointed out, the
defined constants should only be used in assignments, not in tests.

>The correct -- and impractical -- solution is to redefine the languge
>to allow the following defines:

>   #define FALSE  0
>   #define TRUE   [-inf .. -1, 1 .. inf]

Even if the language allowed this definition, it is only useful in
tests, where the defined constants should be missing anyway.  It would
be very difficult to know what happened in an assignment.

>Now in this more powerful language we can assume that (i != FALSE)
>implies (i == TRUE), where equality with TRUE is defined the same way
>as set membership.

The language would certainly be different.  "More powerful" is a claim
I'd debate.  I see little merit in being able to define things in this
way.

>But C and C++ aren't rich enough to allow this, so let's just stick
>with 0 and 1, or ZERO and ONE if you prefer.

Let's just avoid ZERO and ONE.  Better yet, redefine them and see what
happens :-)

>If you MUST define TRUE and FALSE, they should be tested with these
>macros:

>   #define istrue(i) ((i) != 0)
>   #define isfalse(i) ((i) == 0)

>Now !istrue(i) does imply isfalse(i), so we're back to a clean
>boolean approach.

As long as this is comp.lang.c++ and not comp.lang.c, why not just let
those who like to use int for boolean use int, and let those who
feel a strong need for a boolean type define one?

The language and existing libraries speak for themselves.  We can argue
all day about whether functions which return conceptual booleans (zero
vs. nonzero) should be made to return 0 and 1 specifically.  The fact
is that there are functions out there that return nonzero values
besides 1 and intend for the caller to interpret that as a "true".

My own $.02 would be to create an enum such as
    enum EBool { False=0, True=1 };
The set of values for anything of type EBool would be {False,True} only.
For any expressions of type EBool, all nonzero values compare equal.

And if you want automatic conversion between boolean and integer types,
create a class CBool that does those conversions automatically.  Make
construction of a CBool with any nonzero value store a 1 in the CBool.
Make assignment to a CBool of any nonzero value store a 1 in the CBool.
Then you could design a function to return a CBool and code it to return
any integer expression.
--
Kevin J. Hopps   e-mail: kjhopps@mmm.com
3M Company   phone: (612) 737-3300
3M Center, Bldg. 235-3B-16 fax: (612) 737-2700
St. Paul, MN 55144-1000      ** USE kjhopps@mmm.com FOR E-MAIL REPLIES **




Author: kanze@us-es.sel.de (James Kanze)
Date: 21 Jul 93 15:26:16
Raw View
In article <nagleCADIu5.LMI@netcom.com> nagle@netcom.com (John Nagle)
writes:

|> jimad@microsoft.com (Jim Adcock) writes:
|> >So, if we are to avoid breaking existing code in lots of places, what
|> >properties would a "bool" type have?

|>      Here's a compatible possiblity:

|> EXTENSION

|>  A new type, type "boole" is defined.  "boole" has two values,
|> "true" and "false".  All relational operators return results of type
|> "boole".  "If" and "?" expect an argument of type "boole".  A value
             ^^^^     ^^^

As does 'while', I suppose.

|> of type "boole" requires at least one bit of space.  The logical operators
|> "&&" and "||" return results of type "boole".

|> BACKWARDS COMPATIBILITY FEATURES

   [implicit conversions deleted...]

To be useful, the implicit conversions would all have to be declared
obsolescent features, to be removed in a future version of the
standard.

In the absolute, I would agree with this proposal, and I regret that I
didn't actually submit it to the standards committee several years
ago.  As a practical point now, however, adding a new type (with a
plethora of implicit conversions) introduces a significant instability
in the core parts of the language, which the standards committee would
then have to work out.  While such an effort is not overwhelming, and
I think would result in a great improvement in the language, doing so
now would inevitably cause a significant delay in the standard, which
I do not think we can afford.  (On the other hand, namespaces wrecks
even more havoc with the core, for considerably less advantages, and
it was adapted in Munich, so your proposal may actually stand a
chance.)
--
James Kanze                             email: kanze@us-es.sel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                   -- Beratung in industrieller Datenverarbeitung