[comp.lang.c] Grouse: What's the point of enum?

rogue@cellar.UUCP (Rogue Winter) (04/18/91)

When I wanted to start learning C, I expected enumerated types to be very 
useful in combination with the increment and decrement operators.  I hoped to 
be able to use printf(...%s...) to show the named value I'd given a constant.

Neither experiment had the desired effect.  I'm sure you all know the results 
of such operations involved.  The point is, if increment operators on 
enumerated variables don't produce increments of the defined values in the 
enum statement (and enumerated variables are capable of having values
not included in the explicit declarations), why bother declarig values for 
them?

If the names given to enumerated values cannot be printed, why do they exist? 
The only purpose I can see is that they become local symbolic constants.

Forgive a young novice her screed, but this just don't seem kosher.

Rogue Winter      : "How can you say I only protected people in South
rogue@cellar.uucp : Philadelphia?  I protected people all over this city; it
uunet!cellar!rogue: didn't matter if they were in South Philadelphia or
Cellar 215/3369503: Northeast Philadelphia."  -- Frank Rizzo, 4/12/91

u-beasth%peruvian.utah.edu@cs.utah.edu (bryant eastham) (04/18/91)

  Why ignore a construct that CAN give a clearer meaning to your programs?
Using an enum can:

   1) Allow a sequence of values to be assigned to identifiers
      without a bunch of #defines. (Not really a big benefit.)

   2) Allow the compiler to flag type violations on those constants. The
      other option would allow any integer to be passed, where using an
      enum can be checked. This is a considerable advantage.

  In general: Use what they give you to the best advantage!

  Bryant Eastham
  A programmer who cannot live without nested #includes OR enums.

henry@zoo.toronto.edu (Henry Spencer) (04/18/91)

In article <gu1k13w164w@cellar.UUCP> rogue@cellar.UUCP (Rogue Winter) writes:
>If the names given to enumerated values cannot be printed, why do they exist? 

Rumor hath it that they were an implementation kludge after somebody ran out
of symbol-table space in the preprocessor and couldn't expand it because of
address-space limitations on an old machine.  The fast answer is that, as
you have surmised, they aren't good for much.  They don't fit the rest of
the language very well, and they were never thought through very clearly
until X3J11 tried to figure out what they should mean in ANSI C... at which
point it was discovered that existing implementations varied so much that
it was impossible to do anything ambitious with them.  I'm told that there
was considerable sentiment for leaving them out of ANSI C entirely.

Just ignoring them is the simplest thing to do.
-- 
And the bean-counter replied,           | Henry Spencer @ U of Toronto Zoology
"beans are more important".             |  henry@zoo.toronto.edu  utzoo!henry

torek@elf.ee.lbl.gov (Chris Torek) (04/19/91)

>>[enumerated types are ridiculously weak; why do they exist at all?]

In article <1991Apr18.153418.13527@zoo.toronto.edu> henry@zoo.toronto.edu
(Henry Spencer) writes:
>Just ignoring them is the simplest thing to do.

It is sometimes nice to have a symbolic debugger print

	state = TCPSTATE_ESTABLISHED

or whatever, and it is sometimes nice to allow the compiler to choose
the types and values of enumeration variables and constants.  A few
compilers will also warn about `mixed up' enumerations (enum apple
with enum orange).  That makes three tiny points in favour :-)
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

pds@lemming.webo.dg.com (Paul D. Smith) (04/19/91)

[] On 18 Apr 91 04:26:15 GMT, rogue@cellar.UUCP (Rogue Winter) said:

RW> If the names given to enumerated values cannot be printed, why do
RW> they exist?  The only purpose I can see is that they become local
RW> symbolic constants.

They are basically just for the edification of the programmer.  It is
a handy way to state that a variable of the enum type should contain
one of the enumerated values, and no others.  With a regular
preprocessor constant there is nothing to indicate that the variable
can't contain other values, short of putting in a comment to that
effect.  With enums the compiler could generate a warning.

Some compilers can pick the size of the integer in which the enum is
stored based on the size of the largest (or sometimes smallest)
number: thus if your enum values were only 1-5 you'd get a short or
even a char, but if your values contained something like 1000000 you
get an int or long (depending on your architecture).  Usually this
is only useful to try to force all enums to be the native size of the
CPU (since this is the most efficient size), unless they absolutely
can't fit.

Also, most modern debuggers are quite good at noticing when something
is an enum and *do* in fact print the symbolic form (usually in
addition to the numeric form) during debugging.  This makes it quite
handy from the programmer's point of view.

If you think about it, there is no way you could have enums be
printable in string form without introducing some new syntax into C:
how would the compiler know when to interpret the value of the
variable as an integer (enum) and when to interpret it as a string?
The compiler obviously can't recognize that you're passing the enum to
a printf with a "%s" argument, so what if you just wanted to pass the
value of the enum to a function?  You'd need some new syntax to say
"use the stringified name of this enum" rather than the enum value.

All in all, enums are just syntactic sugar.  But some syntactic sugar
can make your programming life much nicer, IMHO, and enums do this
quite well without getting in the way of the "spirit of C".

                                                                paul
-----
 ------------------------------------------------------------------
| Paul D. Smith                          | pds@lemming.webo.dg.com |
| Data General Corp.                     |                         |
| Network Systems Development Division   |   "Pretty Damn S..."    |
| Open Network Systems Development       |                         |
 ------------------------------------------------------------------

toma@swsrv1.cirr.com (Tom Armistead) (04/19/91)

In article <gu1k13w164w@cellar.UUCP> rogue@cellar.UUCP (Rogue Winter) writes:
>When I wanted to start learning C, I expected enumerated types to be very 
>useful in combination with the increment and decrement operators.  I hoped to 
>be able to use printf(...%s...) to show the named value I'd given a constant.
>
>Neither experiment had the desired effect.  I'm sure you all know the results 
>of such operations involved.  The point is, if increment operators on 
>enumerated variables don't produce increments of the defined values in the 
>enum statement (and enumerated variables are capable of having values
>not included in the explicit declarations), why bother declarig values for 
>them?
>
>If the names given to enumerated values cannot be printed, why do they exist? 
>The only purpose I can see is that they become local symbolic constants.
>
>Forgive a young novice her screed, but this just don't seem kosher.
>
>Rogue Winter      : "How can you say I only protected people in South
>rogue@cellar.uucp : Philadelphia?  I protected people all over this city; it
>uunet!cellar!rogue: didn't matter if they were in South Philadelphia or
>Cellar 215/3369503: Northeast Philadelphia."  -- Frank Rizzo, 4/12/91

A few reasons for enums:

  When in a symbolic debugger, you can display an enum variables contents and
  get the text associated with the value, where a define only shows the value
  (unless you have a really smart debugger).

  When used in a switch statememt for some C compilers), will not let you
  have case elements that aren't part of the emumeration. (i.e. better
  type checking).

  I've used enum's to generate some pretty complex types where certain bit
  patterns made something belong to a certain class. After getting this set up,
  it was very easy to just insert a new element in the middle of the enum,
  where using defines would have caused me to do math for each element I
  added.

From the Second Edition of K&R: page 39
  Enumerations provide a convenient way to associate constant values with
  names, an alternative to #define with the advantage that values can be
  generated for you. ...

Tom
-- 
Tom Armistead - Software Services - 2918 Dukeswood Dr. - Garland, Tx  75040
===========================================================================
toma@swsrv1.cirr.com                {egsner,letni,ozdaltx,void}!swsrv1!toma

ts@cup.portal.com (Tim W Smith) (04/19/91)

Wow!  Both Henry Spencer and Chris Torek missed the point of enumerated
types... next thing you know, getting involved in a land war in Asia
will be a good idea.

Anyway, the real point is to allow lower case names for constants.  If
you try this in a header file:

	#define opened 1
	#define closed 2

everyone will scream that you should have said

	#define OPENED 1
	#define CLOSED 2

whereas, if you instead go

	enum state { opened=1, closed };

people who read the code will be so busy trying to remember what the
heck and 'enum' is that they won't realize you've snuck in lower case
constant names.

						Tim Smith

steve@taumet.com (Stephen Clamage) (04/21/91)

ts@cup.portal.com (Tim W Smith) writes:

>Anyway, the real point is to allow lower case names for constants.  If
>you try this in a header file...

"The" real point, eh?  Seems like we've have more than one good point
mentioned already, but I haven't seen this one yet:

Preprocessor defines have no scope.  They reach into the internals of
structs and functions and can result in mystifying error messages and
hard-to-find bugs.  The enumeration names are scoped, and can be made
local to functions if desired, and can be locally overridden inside
functions which don't know and don't want to know about a #define (or
enum) buried inside some nested include file.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

burow@cernvax.cern.ch (burkhard burow) (04/21/91)

[] On 18 Apr 91 04:26:15 GMT, rogue@cellar.UUCP (Rogue Winter) said:

RW> If the names given to enumerated values cannot be printed, why do
RW> they exist?  The only purpose I can see is that they become local
RW> symbolic constants.

Below, in enum.h, is a souped up 'enum' and an example program follows in
enum.c. Cut 'em out, compile, and a demo's ready for you.

In no more code than a regular typedef enum, the macros ENUMn(...), where n is
the number of constants in the enumeration, provides:
i)   the constants.
ii)  the number of constants.
iii) an array of the constant names as strings.
iv)  a macro to recognize a particular constant in the enumeration.
v)   addition of another constant to the enumeration without changing a single
      line of code elsewhere.

WARNING: In the following, as far as I know, the only deviation from ANSI C is
the '/**/' kludge for the preprocessor concatenation operator '##'. I use ENUMn
on: VAX VMS: C 3.1 and MIPS Computer Systems 2.0 (e.g. SGI and DECstations).
Some 'guidelines' for these two machines are given in enum.h.


May it amuse,
burkhard            burow@vxdesy.cern.ch

------------cut here for enum.c------------------------------------------------
/* enum.c  An example of the macros in enum.h */
/* Burkhard Burow, University of Toronto, 1990. */

#include "enum.h"
#include <stdio.h>

#define MIN(A,B) ((A)<(B)?(A):(B))

/* Note that adding another constant to the following line requires no change
in any other line of code. */
#ifndef mips
ENUM5(LIST, JUST, SOME, SILLY, STUFF, AGAIN);
#else
ENUM5(LIST,JUST,SOME,SILLY,STUFF,AGAIN);
#endif

main ()
{
int i, loop; char s[99]; 
LIST list;

puts("The enum 'LIST' has the following enumerated constants.");
for (i=0; i<(int)LISTS; i++) printf("  %s", enum_str(LIST)[i]);

puts("\n Please enter one of the above constants: ");
gets(s);

for (loop=0; loop<4; loop++) {
  switch (loop) {
  case 0: printf("An exact comparison");
          ENUMno(LIST, s, 9999,                                     i);
          break;
  case 1: printf("A comparison of the first strlen('LIST' element) characters");
          ENUMno(LIST, s, strlen(enum_str(LIST)[i]),                i);
          break;
  case 2: printf("A comparison of the first strlen(%s) characters",s);
          ENUMno(LIST, s, strlen(s),                                i);
          break;
  case 3: printf("A comparison of the first ");
          printf("MIN(strlen(%s), strlen('LIST' element) ) characters", s);
          ENUMno(LIST, s, MIN(strlen(s),strlen(enum_str(LIST)[i])), i);
          break;
  }
  if (i==(int)LISTS) 
    printf("\n does not recognize %s as a constant in 'LIST'\n\n", s);
  else 
    printf("\n recognizes %s as the constant %s in 'LIST'\n\n", s,
           enum_str(LIST)[i]);
}
}

------------cut here for enum.h------------------------------------------------
/* enum.h */
/* Burkhard Burow, University of Toronto, 1990. */

#ifndef __ENUM_LOADED
#define __ENUM_LOADED	1

static char *nonindent(char *s) { while(*s==' ')s++; return s; }


#include <stdio.h>
#include <string.h>

/* Souped up enum => ENUM1->ENUMn. Typedef's NAME as enumerated with the n given
   constants. enum_str(NAME) is an array of the constants as strings and NAMES
   is the number of constants. Macro ENUMno recognizes constant from a string.
VAX WARNING: The arguments to ENUMn should be be immediately followed by the ','
         or ')'. Trailing whitespace characters are part of the argument, and as
         such will be included in the string created for each tag and hence 
         will cause difficulties when ENUMno searching for tags. 
MIPS WARNING: Same as the VAX but space after the comma and before the argument
         is also included in that argument. Therefore to maintain portability
         across VAXen and MIPS', remove all spaces in ENUMi(...) and
         in enum_str(...) calls. Alternatively, to preserve readability, use
         #ifndef mips
           for calls to ENUMi(..) and enum_str(...) with spaces for readability 
            and behind the 
         #else
           have the same calls with all spaces removed. 
N.B. MIPS machines include SGI's and DECstations. */

#define enum_str(NAME) ENUM_/**/NAME
#define ENUMNO(ENUM_NAME, NAMES, STRING, LENGTH, NO)                           \
 for (NO=0; NO<(int)NAMES; NO++)                                               \
   if (strncmp(STRING,ENUM_NAME[NO],LENGTH)==0) break;
#define ENUMno(NAME, STRING, LENGTH, NO)                                       \
 ENUMNO(enum_str(NAME), NAME/**/S, STRING, LENGTH, NO)

/* char *ENUM_NAME[]; int NAMES; char *STRING; int LENGTH; int NO;
  - NO returns enum. tag of ENUM_NAME matching LENGTH characters of STRING.
  - If none of the NAMES tags match STRING, NO returns NAMES.
  - For exact  comparison with STRING      use LENGTH as a_really_big_int.
  - For prefix comparison on   STRING      use LENGTH as strlen(ENUM_NAME[NO]). 
  - For prefix comparison on   ENUM_NAME's use LENGTH as strlen(STRING).      
  - For prefix comparison on   either      use LENGTH as 
                              MIN(strlen(STRING),STRLEN(ENUM_NAME[NO])).      */

#define ENUM1(NAME, A)               typedef enum{A,NAME/**/S}NAME;            \
 static char *enum_str(NAME)[] = {"A"}
#define ENUM2(NAME, A,B)             typedef enum{A,B,NAME/**/S}NAME;          \
 static char *enum_str(NAME)[] = {"A","B"}
#define ENUM3(NAME, A,B,C)           typedef enum{A,B,C,NAME/**/S}NAME;        \
 static char *enum_str(NAME)[] = {"A","B","C"}
#define ENUM4(NAME, A,B,C,D)         typedef enum{A,B,C,D,NAME/**/S}NAME;      \
 static char *enum_str(NAME)[] = {"A","B","C","D"}
#define ENUM5(NAME, A,B,C,D,E)       typedef enum{A,B,C,D,E,NAME/**/S}NAME;    \
 static char *enum_str(NAME)[] = {"A","B","C","D","E"}
#define ENUM6(NAME, A,B,C,D,E,F)     typedef enum{A,B,C,D,E,F,NAME/**/S}NAME;  \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F"}
#define ENUM7(NAME, A,B,C,D,E,F,G)                                             \
 typedef enum{A,B,C,D,E,F,G,NAME/**/S}NAME;                                    \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G"}
#define ENUM8(NAME, A,B,C,D,E,F,G,H)                                           \
 typedef enum{A,B,C,D,E,F,G,H,NAME/**/S}NAME;                                  \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H"}
#define ENUM11(NAME, A,B,C,D,E,F,G,H,I,J,K)                                    \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,NAME/**/S}NAME;                            \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K"}
#define ENUM12(NAME, A,B,C,D,E,F,G,H,I,J,K,L)                                  \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,NAME/**/S}NAME;                          \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                                  "L"}
#define ENUM13(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M)                                \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,NAME/**/S}NAME;                        \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                                  "L","M"}
#define ENUM15(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O)                            \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,NAME/**/S}NAME;                    \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                                  "L","M","N","O"}
#define ENUM16(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P)                          \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,NAME/**/S}NAME;                  \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                                  "L","M","N","O","P"}
#define ENUM20(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U)                  \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,NAME/**/S}NAME;          \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                                  "L","M","N","O","P","Q","R","T","U"}
#define ENUM46(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,        \
 AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV)               \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,               \
 AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,NAME/**/S}NAME;\
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                      "L","M","N","O","P","Q","R","T","U","V","W","X","Y","Z", \
  "AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK",                      \
  "AL","AM","AN","AO","AP","AQ","AR","AT","AU","AV"}
#define ENUM48(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,        \
 AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,AW,AX)         \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,               \
 AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,AW,AX,         \
 NAME/**/S}NAME;                                                               \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                      "L","M","N","O","P","Q","R","T","U","V","W","X","Y","Z", \
  "AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK",                      \
  "AL","AM","AN","AO","AP","AQ","AR","AT","AU","AV","AW","AX"}
#define EXPAND16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P)                              \
 A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P
#define QEXPAND16(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P)                             \
 "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"
/* N.B. e.g. ENUM78(NAME, 52 args, (16 args) ) req.d because VAX C limits 
   number of macro args to 64. */
#define ENUM78(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,        \
 AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,AW,AX,AY,AZ,   \
 BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,ARGS16)                                   \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,               \
  AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,AW,AX,AY,AZ,  \
  BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,EXPAND16/**/ARGS16,NAME/**/S}NAME;       \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                      "L","M","N","O","P","Q","R","T","U","V","W","X","Y","Z", \
  "AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK",                      \
  "AL","AM","AN","AO","AP","AQ","AR","AT","AU","AV","AW","AX","AY","AZ",       \
  "BA","BB","BC","BD","BE","BF","BG","BH","BI","BJ","BK","BL",                 \
  QEXPAND16/**/ARGS16}
#define EXPAND18(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)                          \
 A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R
#define QEXPAND18(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)                         \
 "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R"
/* N.B. ENUM80(NAME, 52 args, (18 args) ) syntax req.d because VAX C limits 
   number of macro args to 64. */
#define ENUM80(NAME, A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,        \
 AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,AW,AX,AY,AZ,   \
 BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,ARGS18)                                   \
 typedef enum{A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,T,U,V,W,X,Y,Z,               \
  AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AT,AU,AV,AW,AX,AY,AZ,  \
  BA,BB,BC,BD,BE,BF,BG,BH,BI,BJ,BK,BL,EXPAND18/**/ARGS18,NAME/**/S}NAME;       \
 static char *enum_str(NAME)[] = {"A","B","C","D","E","F","G","H","I","J","K", \
                      "L","M","N","O","P","Q","R","T","U","V","W","X","Y","Z", \
  "AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK",                      \
  "AL","AM","AN","AO","AP","AQ","AR","AT","AU","AV","AW","AX","AY","AZ",       \
  "BA","BB","BC","BD","BE","BF","BG","BH","BI","BJ","BK","BL",                 \
  QEXPAND18/**/ARGS18}


#endif					/* __ENUM_LOADED */

marks@cbnewsl.att.com (mark.e.smith) (04/22/91)

In article <678@taumet.com> steve@taumet.com (Stephen Clamage) writes:
>ts@cup.portal.com (Tim W Smith) writes:
>
>>Anyway, the real point is to allow lower case names for constants.  If
>>you try this in a header file...
>

I love it.  Score one for the anti-style guide side.

>
>Preprocessor defines have no scope.  They reach into the internals of
>structs and functions and can result in mystifying error messages and
>hard-to-find bugs.  The enumeration names are scoped, and can be made
>local to functions if desired, and can be locally overridden inside
>functions which don't know and don't want to know about a #define (or
>enum) buried inside some nested include file.

Yes.  The answer hints at the model, which is that an enum defines a type,
i.e. a set of values.  Defining types is a Good Thing.  Otherwise, there's
nothing in the program syntax which hints at the relationship among the values.

Compare for example the three styles:

#define APPLE 1
#define ORANGE 2

vs.

#define APPLE 1
#define ORANGE ( APPLE + 1 )

which is better, since at least we have some clue that an apple and an
orange are somehow related; vs.

enum { APPLE = 1, ORANGE } ;

which is explicit.

Mark Smith

rogue@cellar.UUCP (Rogue Winter) (04/25/91)

ts@cup.portal.com (Tim W Smith) writes:

> Wow!  Both Henry Spencer and Chris Torek missed the point of enumerated
> types... next thing you know, getting involved in a land war in Asia
> will be a good idea.
> 
> Anyway, the real point is to allow lower case names for constants.  If
> 

[code deleted, The President's previous statements are inoperable]

> people who read the code will be so busy trying to remember what the
> heck and 'enum' is that they won't realize you've snuck in lower case
> constant names.
> 
> 						Tim Smith


Well, since I'm self-taught and don't have anyone looking over my shoulder at 
my bad habits, I tend to violate such canons amyhow.  I've used all caps to 
define constants and mixed case to define macros and nobody else has ever had 
to know the wiser.  (oops, now I've just blurted it out)

Since the only reason I sould come up with for using enums was as an 
alternate declaration of constants, I had to consider it useless, since it 
takes more expressions to use an enum variable than a defined constant.

Rogue Winter      : "How can you say I only protected people in South
rogue@cellar.uucp : Philadelphia?  I protected people all over this city; it
uunet!cellar!rogue: didn't matter if they were in South Philadelphia or
Cellar 215/3369503: Northeast Philadelphia."  -- Frank Rizzo, 4/12/91