cim2@pyuxv.UUCP (Robert L. Fair) (06/13/86)
At the risk of being flamed, I've been using enums for a proper boolean datatype for years: typedef enum { false=0,true } bool; bool flag=false; if(!flag) ... This has _lots_ of advantages over the usual #defines - especially with a decent compiler which will barf on constructs like: flag=10; /* correct syntax error,10 is neither true nor false */ or enum states {activate,inactive,comatose} state; flag=state; /* correct syntax error - a state isn't a boolean */ Many current C compilers now implement enums properly (i.e. each enumeration is a distinct type) yet they are hardly ever used. Any comments why not ? Rob Fair Bell Communications Research ihnp4!pyuxv!cim2
guy@sun.uucp (Guy Harris) (06/13/86)
> At the risk of being flamed, I've been using enums for a proper boolean > datatype for years: > > typedef enum { false=0,true } bool; > ... > This has _lots_ of advantages over the usual #defines - especially with > a decent compiler which will barf on constructs like: > > flag=10; /* correct syntax error,10 is neither true nor false */ Well, I doubt the compiler would claim that it was a syntax error; PCC complains about an "enumeration type clash" (which is a warning, rather than an error). This is an advantage of "enum"s, though, even though it's just a warning. If you fix some bugs in "lint", it even checks that you aren't passing an "enum" to a routine expecting an "int" or another "enum", or an "int" to a routine expecting an "enum". Also, if you use "enum"s rather than #define constants, a reasonable symbolic debugger will, when asked to print an "enum" variable's value, print it by its "enum" element name ("dbx" does, I don't know about the others). However, there is one problem with using "enum"s for a boolean type; "Boolean" expressions in C have type "int", not "enum", so bool flag = (foobar == 33); will cause an "enumeration type clash" error; you have to cast the expression to type "bool" to silence the compiler. Note that "enum"s, according to the current C draft, are basically integral types; this means that assignments of "int"s to "enum"s are legal, although this doesn't mean the compiler can't produce a warning. > Many current C compilers now implement enums properly (i.e. each enumeration > is a distinct type) What C compilers don't? > ...yet they are hardly ever used. Any comments why not ? Habit? -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)
chris@umcp-cs.UUCP (06/15/86)
In article <210@pyuxv.UUCP> cim2@pyuxv.UUCP (Robert L. Fair) writes: >At the risk of being flamed, I've been using enums for a proper boolean >datatype for years: > > typedef enum { false=0,true } bool; > > bool flag=false; > >... a decent compiler which will barf on constructs like: > > flag=10; /* correct syntax error,10 is neither true nor false */ >or > enum states {activate,inactive,comatose} state; > flag=state; /* correct syntax error - a state isn't a boolean */ Neither of these is syntactically incorrect; a compiler that gives a syntax error is printing the wrong message. Rather, these are semantically incompatible (though this depends on your semantics). >Many current C compilers now implement enums properly (i.e. each enumeration >is a distinct type) yet they are hardly ever used. Any comments why not ? PCC does about half the job, mostly because it gets stickier as you go along. For example, should printf() be able to print enumerations? If so, should it print them as integers or as strings? Should scanf() handle enumerations? Where is the line between the integer/enumeration split? The latest-I-have-seen ANSI X3J11 draft has `enum's defined simply as aliases for integers, which means one might as well just use `#define'. . . . -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu
donn@utah-gr.UUCP (Donn Seeley) (06/16/86)
I was informed by Rob Pike not too long ago that at least at the Labs, enums are ints: enumeration constants are symbolic integer constants and enumeration variables are simply ints. Their compiler doesn't emit any 'enumeration type clash' warnings and performs proper integer operations on enums such as shifts (the BSD PCC won't permit shifts of enum variables). The proposed draft ANSI C standard doesn't seem to require that compilers treat enums as anything other than ints. If people are writing programs which employ enums strictly as ints, the utility of enums in type verification seems to be nil and compiler warnings will just be obnoxious. The situation with enums reflects the situation with typedefs in an odd way -- despite appearances, neither construct defines a 'new' type. As Guy Harris notes, enums are useful as replacements for preprocessor constants and can serve as a debugging aid for programs like 'dbx'. Given their limited application it's easy to see why they haven't caught on. Donn Seeley University of Utah CS Dept donn@utah-cs.arpa 40 46' 6"N 111 50' 34"W (801) 581-5668 decvax!utah-cs!donn
faustus@ucbcad.BERKELEY.EDU (Wayne A. Christopher) (06/17/86)
> typedef enum { false=0,true } bool; > > Many current C compilers now implement enums properly (i.e. each enumeration > is a distinct type) yet they are hardly ever used. Any comments why not ? The problems come when you write: bool b; int a, c; b = (a == c); My compiler gives an "enumeration type clash". It would seem that you can't legally convert integers to enum members... Wayne
alex@ucla-cs.ARPA (Alex Quilici) (06/17/86)
>The problems come when you write: > > bool b; > int a, c; > > b = (a == c); > >My compiler gives an "enumeration type clash". It would seem that you >can't legally convert integers to enum members... yes, you can. c just won't do the conversion for you automatically. try using a cast: b = (bool) (a == c); i frequently use enums to define constants that indicate various errors. i find that whenever i have to worry about many errors typedef enum {NOPASS, BADRD, ... } ERROR; is more convenient than #define NOPASS 1 #define BADRD 2 ... i also find that my programs are more readable because the compiler forces me to declare all variables or functions that hold or return an error status to be of type ERROR, rather than simply int. alex
mike@peregrine.UUCP (Mike Wexler) (06/17/86)
In article <210@pyuxv.UUCP> cim2@pyuxv.UUCP (Robert L. Fair) writes: >Many current C compilers now implement enums properly (i.e. each enumeration >is a distinct type) yet they are hardly ever used. Any comments why not ? There are(at least) two reasons. First, a lot of people don't know that there c compiler has enum types since they have a C compiler thats uses k&r as the manual and k&r doesn't describe enum types. Second, they would limit the portability of the application since enum types are not yet universal. I think that the ANSI standard will help solve both of these problems since the new standard document describing the language will describe enum's(they are in the standard, aren't they?) and compiler writers will have more incentive to support this feature. Not being ANSI compatible will cause a compiler writer to receive many complaints(and probably less sales). -- Mike Wexler Email address:(trwrb|scgvaxd)!felix!peregrine!mike Tel Co. address: (714)855-3923 ;-) Internet address: ucivax@ucbvax.BERKELY.EDU!ucivax%felix!mike@peregrine :-(
rbutterworth@watmath.UUCP (Ray Butterworth) (06/18/86)
The X3J11 draft says that enums are type (int). This is probably a mistake since they should be at least type (size_t) as they are handy for defining specific index values into arrays. But even though they are more or less equivalent to #defines as far as the compiler is concerned, there is no reason that lint can't treat them specially. In particular it should allow subscripting, switching, and if(b) and if(!b) without any complaint, but it should complain about function parameters or other attempts to implicitly cast them to a different type. Incidentally, since they are used the same as #define manifests, as a matter of style we always make the enum constant have an all upper-case name (e.g. TRUE) just as we do for all #define manifest names. As far as the programmer is concerned they are used identically so he shouldn't need to know whether they are enums or manifests. And if we have to move to a compiler that doesn't have enums, making them manifests in the header files is easy. Similarly we make #define macros all upper-case if they have side-effects on the arguments, but all lower-case if they are indistinguishable from functions in usage. As was pointed out, the biggest problem with an enum Boolean is in assigning "b=(a==c)" or "return (a==c)". We use this typedef frequently, and this particular problem doesn't arise that often. When it does, it really isn't that difficult to have to say "b=(Boolean)(a==c)" or "return (Boolean)(a==c)", or to have #define BOOLEAN(x) ((Boolean)(x)) and then "b=BOOLEAN(a==c)" or "return BOOLEAN(a==c)".
guy@sun.UUCP (06/19/86)
> The proposed draft ANSI C standard doesn't seem to require that compilers > treat enums as anything other than ints. If people are writing programs > which employ enums strictly as ints, the utility of enums in type > verification seems to be nil and compiler warnings will just be obnoxious. I wouldn't say their utility was nil. I don't know how many people literally use them strictly as ints; it would seem kind of silly to set some "int" variable to 33 by doing enum bag_of_numbers { thirty_three = 33, sixty_six = 66, ... }; variable = thirty_three; I suspect that in most cases an "enum" is being used roughly the same way it's used in other languages, to represent a member of a collection of named objects. The difference in C is that you can bind values to these names, either because the values are imposed by some external agency (error codes in a protocol or from an external device, etc.) or because one wishes to implement some function whose domain is the set of values for that "enum" using some efficient trick involving arithmetic on the underlying value of the "enum". As such, enum apples { jonathan, ... } apple; enum oranges { jaffa, ... } orange; if (apple == orange) { ... } would be, well, comparing apples and oranges, and should get a warning. You can use casts to override this; if (apple == (enum apples) orange) should not give a warning. Another reason why "enum"s need to be treated as ints is that you may want to use them as subscripts. Other languages handle this by supporting subrange types and treating an array as a mapping from some integral or enumerated type to some other type, so that you declare the bounds of an array by giving the type to be used as an index. You don't do this in C (for one thing, C doesn't support subranges, so you can't declare a 10-element array by saying its index is the subrange 1..10; for another thing, C's notion of array indexing is a bit strange), so you can't say "this array has "enum apples" as its subscript. I hope future ANSI C compilers don't treat "enum"s totally like arrays. For one thing, they'd better not put "this is just an integral type of some particular size" in the debugger's symbol table; they should specify that it's an enumerated type and give the names of the type's values. -- Guy Harris {ihnp4, decvax, seismo, decwrl, ...}!sun!guy guy@sun.com (or guy@sun.arpa)