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 ...
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
akenning@pico.oz (Alan Kennington) (09/26/89)
In article <1989Sep22.073138.19684@lth.se> dag@Control.LTH.Se (Dag Bruck) writes: >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: [...] If a boolean type is required, it can easily be provided in C++, with whichever properties are desired. Some people like, for instance to have: enum boolean { false, true, maybe }; There must be some way of deciding which types should be built-in and which should be user-defined. Otherwise, everything would have to be put in, and then people would complain that the implementation wasn't quite what they wanted. I think it would be better to discuss the _principles_ of which types become built-in and which don't, rather than proposing particular types, e.g. "string", "complex", which should be built-ins. It seems to me that there is a very simple rule which fits C. That is that a type should be built in if a wide range of common architectures explicitly support it. Hence int, long, char, float, double, pointer-to-something, are all natural built-in types, which have machine instructions to support them. However, the single-bit boolean variable has rather few machines which support it per se. Most machines do operations on the whole byte, word, or longword, not just on one bit. These operations are indeed specifically referred to by C operations: &, |, etc. So I think that the time to add "boolean" to the built-in operators will be when common architectures support single-bit data representations and operations that are more efficient than the corresponding operations on whole bytes, words or longwords. If people want a boolean type, then the C++ classes are meant for precisely that purpose. It is contrary to the C/C++ minimalist spirit to burden the language with a non-machine-supported type. I am right, am I not? ("I'm right, aren't I?" is criticisable English.) Alan Kennington.
bright@Data-IO.COM (Walter Bright) (09/26/89)
In article <9464@attctc.Dallas.TX.US> wjf@attctc.Dallas.TX.US (Jesse Furqueron) writes: <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. <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. What's the point? !0 == 1. Period. It is not going to change. !0 is not more portable or more readable. I used to extensively use: typedef int bool; #define TRUE 1 #define FALSE 0 I eventually gave this up because: 1. Name space collisions with other people's code. 2. Frequent confusion of whether TRUE meant !=0 or if it really meant 1. Note that functions like isalpha() return !=0 or 0, not 1 or 0. This means that if you wish to precisely use TRUE/FALSE, you have to write code like condition = (isalpha(c) != 0); which is an efficiency problem. Now, I simply use code like: /**************************** * Test for a condition. * Returns: * 0 condition not satisfied * !=0 condition is satisfied */ int testcondition(args) ... P.S. One of my pet peeves is code like: #ifdef notdefined instead of #if 0 For the former, I have to grep all the c, h and makefiles to make sure notdefined is never defined. For the latter, there can be no problem. Ditto for stuff like while (ALWAYS) loop_forever instead of while (1)
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").
dld@F.GP.CS.CMU.EDU (David Detlefs) (09/26/89)
Several of the posts on this subject have been of the form "why bother if you've already got the int type that does everything you want?" I kind of agree, but I kind of don't: I think you would only really gain something if you really went for it and made Bool (or whatever) part of the language. Specifically: 1) "If," "while," "for," and "do" statement tests would require a boolean. 2) Relational operators (==, >, &&, etc) would return a boolean. I think this might result in measurably safer programs. Just think, errors of the form if (i = 0) ... would become errors. (I'm assuming that there is no implicit conversion between int and boolean.) If you don't take the full step (and I have no hope of this actually happening; there are probably good reasons not to do this. Like backwards compatibility) then it's probably not worth doing. Ah well. Dave -- Dave Detlefs Any correlation between my employer's opinion Carnegie-Mellon CS and my own is statistical rather than causal, dld@cs.cmu.edu except in those cases where I have helped to form my employer's opinion. (Null disclaimer.)
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
fishkin@pixar.UUCP (Ken Fishkin) (09/26/89)
In article <2142@dataio.Data-IO.COM> bright@dataio.Data-IO.COM (Walter Bright) writes: ]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. ] ]What's the point? !0 == 1. Period. It is not going to change. !0 is not ]more portable or more readable. I disagree. I have worked in environments where !0 was -1. Setting TRUE to !0 is indeed more portable. Furthermore, it better captures the fact that in 'if' tests, the 'true' branch is taken on non-zero, not just on '1'. -- Ken Fishkin ...ucbvax!pixar!fishkin
sartin@hplabsz.HPL.HP.COM (Rob Sartin) (09/27/89)
In article <DLD.89Sep25164955@F.GP.CS.CMU.EDU> dld@F.GP.CS.CMU.EDU (David Detlefs) writes: >I think this might result in measurably safer programs. Just think, >errors of the form > > if (i = 0) ... > >would become errors. (I'm assuming that there is no implicit >conversion between int and boolean.) and all of the programs of the form: SomeType *Current; while (Current = Foo.Next()) { // Do something with Current } would suddenly become illegal even though that is a common idiom for traversing lists. Rob Sartin internet: sartin@hplabs.hp.com Software Technology Lab uucp : hplabs!sartin Hewlett-Packard voice : (415) 857-7592
roemer@cs.vu.nl (Roemer Lievaart) (09/27/89)
blarson@basil.usc.edu (bob larson) writes: >> I would suggest that the standardized definition be >> const boolean (false=0, true=1); false=(0==1), true=(0==0)
ark@alice.UUCP (Andrew Koenig) (09/27/89)
The trouble at the root of all this discussion is that x == y is defined in C as being an int. This isn't going to change any time soon, and making C++ differ from C in such a fundamental respect seems unlikely to be capable of gaining as much as it would cost. -- --Andrew Koenig ark@europa.att.com
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 | \*------------------------------------------------------------------------*/
nagle@well.UUCP (John Nagle) (09/27/89)
In article <6897@pixar.UUCP> fishkin@pixar.UUCP (Ken Fishkin) writes: > I disagree. I have worked in environments where !0 was -1. That's an incorrect implementation in both C and C++. K&R reads (sec. 4.6): "The unary negation operator converts a non-zero or true operand into 0 and a zero or false operand into 1." Strostrup reads (sec 7.2): "The result of the logical negation operator ! is 1 if the valu of its operand is 0, 0 if the value of its operand is non-zero". John Nagle
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)
bright@Data-IO.COM (Walter Bright) (09/28/89)
In article <6897@pixar.UUCP> fishkin@pixar.UUCP (Ken Fishkin) writes: <In article <2142@dataio.Data-IO.COM> bright@dataio.Data-IO.COM (Walter Bright) writes: <]!0 == 1. Period. It is not going to change. !0 is not <]more portable or more readable. < I disagree. I have worked in environments where !0 was -1. <Setting TRUE to !0 is indeed more portable. What compiler is that? It is definitely broken. Did it also evaluate (0==0) as -1? If the only one it got wrong was !0, then setting TRUE to !0 would cause more problems (probably very obscure ones). In general, warping your source code to account for a particularly bad compiler that you may be forced to deal with should be done with #if's. For instance, I've had to deal with a compiler that didn't implement switch statements properly. This is not a reason to abandon using switches. The workaround was to: #if __BRAND_X_C__ if (v == 1) ... else if (v == 2) ... #else switch (v) { case 1: ... case 2: ... } #endif And, of course, reporting the problems to the vendor to try to get them fixed.
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)
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!
news@cs.yale.edu (Usenet News) (09/30/89)
>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. From: zador-anthony@CS.YALE.EDU (anthony zador) Path: zador-anthony@CS.YALE.EDU OK, i'll bite. Esperanto?
lsmith@apollo.HP.COM (Lawrence C. Smith) (10/03/89)
In article <2142@dataio.Data-IO.COM> bright@dataio.Data-IO.COM (Walter Bright) writes: >In article <9464@attctc.Dallas.TX.US> wjf@attctc.Dallas.TX.US (Jesse Furqueron) writes: ><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. ><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. > >What's the point? !0 == 1. Period. It is not going to change. !0 is not >more portable or more readable. Sadly, many C hackers just don't realize how important a clear, readable style is. This last comment reminds of the other fellow who also felt that, because ints *could* be used for booleans then that was *good* and there was no point making things more "complicated". Perhaps these people would also like BLISS, which reduces the number of essential data types to just one... > >I used to extensively use: > typedef int bool; > #define TRUE 1 > #define FALSE 0 >I eventually gave this up because: >1. Name space collisions with other people's code. >2. Frequent confusion of whether TRUE meant !=0 or if it really meant 1. I use something like this: typedef int flag; #define YES (1==1) #define NO (1==0) #define OKAY(x) ((x) != 0) The use of YES, NO, OKAY and flag do not seem to generate much conflict with other people's choices, and the YES and NO macros are guaranteed portable (and I obviously depend on the optimizer to turn (1==1) into the appropriate internal TRUTH value). Since YES and NO always equate to whatever internal values the compiler likes, and since most compilers *will* do constant folding, these work out pretty efficiently. Also, I can now save boolean expressions: flag foo; foo = A == B; With the fairly certain knowledge that if(foo) (or the somewhat ridiculous if(foo == YES)) will work consistantly and correctly. OKAY is used for old C code: foo = OKAY(strcmp("fubar",some_silly_string)) if(foo) ... It's not as good as a rigorously defined built-in type with compiler checking and the like, buts it *is* better than just using 0 and 1 with ints. > Note that functions like isalpha() return !=0 or 0, not 1 or 0. This > means that if you wish to precisely use TRUE/FALSE, you have to write code > like > condition = (isalpha(c) != 0); > which is an efficiency problem. It is like fun. I will grant you that C has twelve ways of doing something because they are, in theory, compiled differently and that some ways are more efficient than others in certain contexts and that the programmer has the power to choose. But this is the modern world!!! In this enlightened day and age, we know that 90% of the execution time is in 10% of the code, and that optimizing code executed once buys nothing. In this enlightened day and age, we know that optimizers will fold, spindle and mutilate our code, and that most of the time the optimizers know more about efficient instruction sequences on CPU x than we do, and that's the way it should be. In this enlightened day and age, we know that condition = (isalpha(c) != 0) will very seldom be an efficiency problem, even assuming the compiler really compiles it that way. >P.S. One of my pet peeves is code like: > #ifdef notdefined >instead of > #if 0 >For the former, I have to grep all the c, h and makefiles to make sure >notdefined is never defined. For the latter, there can be no problem. >Ditto for stuff like > while (ALWAYS) > loop_forever >instead of > while (1) You choose your idiom and you use it. Where I come from, people who write while (1) would be castigated, flagellated and fumigated for not having written for(;;). In other places, you would be taken to task for not writing while(1), or whatever. C has too many different ways of doing things for any of them to be universal without enforcement from training institutions, of which we ain't got. for(;;) was the Stony Brook way, so that's what I learned. Is it still that way? Who knows. It might be, if the same guy is teaching the course. Or maybe they have a new former Berkley guy who likes while(1) or while (1). Of course, they might also have a new wave guy who likes "#define loop while(1) ... loop ..." or even a FORTRAN retread who simply does a "go to loop" at the bottom of his loop. If you want consistant, use Pascal. -- Larry Smith Internet: lsmith@apollo.hp.com UUCP: {decvax,mit-eddie,umix}!apollo!lsmith
lsmith@apollo.HP.COM (Lawrence C. Smith) (10/03/89)
In article <27541@amdcad.AMD.COM> tim@amd.com (Tim Olson) writes: >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? Yes, all of them. This is an example of a "cheap" optimization, one that is relatively easy and safe, most of the time. The fact that it does not do what we would expect does not mean it is wrong, either. !!a == a under the compiler's own built-in logical rules and if(a) will work the same way. I don't think there is a compiler in the world I'd trust to take !!a and turn it into a canonical true/false value. Come on, people! C compilers weren't even required to honor parens until the last ANSI revision, a C compiler is allowed to do *anything it wants* to a program provided the final program is congruent to the input program with repect to the compilers own rules for such changes. No compiler has to compile a++ if ++a gives the same result. No compiler has to compile (a++; b = a-1;) when (b = a++;) means the same thing. This isn't new, the floating point fans have been bitching about this for *years* since it makes C terribly unsafe for floating point, where round-off can smite you a mighty blow without warning. Folks, all this is all just adding weight to the "let's add booleans to C" contingent's argument. -- Larry Smith Internet: lsmith@apollo.hp.com UUCP: {decvax,mit-eddie,umix}!apollo!lsmith
bart@videovax.tv.Tek.com (Bart Massey) (10/04/89)
In article <45fe2dd3.1199f@apollo.HP.COM> lsmith@apollo.HP.COM (Lawrence C. Smith) writes: > In article <27541@amdcad.AMD.COM> tim@amd.com (Tim Olson) writes: > >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. > >| > >| Nice, isn't it. And too real too. > > > >And wrong, too. Do you know of a compiler that does this in the > >general case? > > Yes, all of them. Aiigh! I'm sure I'm about the millionth response to this, but I just can't stand it anymore! "The result of the logical negation operator ! is 1 if the value of its operand is 0, 0 if the value of its operand is non-zero. The type of the result is int. It is applicable to any arithmetic type or to pointers" -- K&R A:7.2, Stroustrup r.7.2 "The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E)." -- ANSI X3J11/88-158 3.3.3.3 19 So anything that is supposed to be a standard C or C++ compiler is *required* to do the right thing! As a test, I tried 4 C compilers we have around: Stanford's V6.0 68k (an ancient PCC based compiler) Greenhills 68k (a modern commercial compiler) BSD 4.3Tahoe VAX (a modern PCC based compiler) GNU GCC1.34 VAX (a cool highly optimizing retargetable compiler) The test code I used was simply: /* test.c */ main( argc, argv ) int argc; char **argv; { printf( "%d\n", (!!(atoi(argv[1]))) ); } All compilers, when invoked with "$(CC) $(MISCFLAGS) -O -o test test.c", produced a binary for which the invocation "./test 2" printed "1". Examination of the assembly code revealed various levels of optimization, but no obvious incorrect code. > This is an example of a "cheap" optimization, one that > is relatively easy and safe, most of the time. The fact that it does not > do what we would expect does not mean it is wrong, either. No, the fact that it does not conform to any accepted C language definition means that it is wrong. Note that your optimization *is* legal if the compiler can somehow tell that it is completely invisible -- the "as-if" rule. I.e., one can legally optimize if( !!a ) printf( "hello\n" ); to if( a ) printf( "hello\n" ); because the second statement behaves as if it were the first in all cases... Enough said. Please try writing some C code before making strong statements about the foibles of existing C compilers. I know of no compiler which will compile my test program above into incorrect code because of a bug involving the optimization of the "booleanizing operator" (sic :-) "!!". If anyone could give me an example of any such compiler that I could independently verify, I'd be truly interested. Bart Massey ..tektronix!videovax.tv.tek.com!bart ..tektronix!reed.bitnet!bart