[comp.lang.c] Question about use of enum in typedef and struct

cavrak@uvm-gen.UUCP (Steve Cavrak) (04/29/88)

Can someone explain why the following uses (abuses?) of typdef and enum
create problems in the struct that follows them?  (The example is taked
from a once working program that was being ported to a new compiler that
is "now ANSI" compliant.  The code has been "tested" on VAX BSD 4.3, VAX
VMS, and Turbo-C.  The "new" compiler is Waterloo C 3.0.)  The available
C documentation is not enlightening.  I'm sure that my Pascal mindset
adds to the confusion.

/*  Imnotok.c								*/
/*  Confusion using enumerated types in structures			*/
/*									*/
/*  The "_ok" declaration is usable in the struct definition AND	*/
/*  the "_to" declaration is usable, BUT				*/
/*  the "_no" declaration generates a syntax error.			*/
/*									*/
/*  Why?								*/
/*  ------------------------------------------------------------------  */
 
typedef int s_state_ok;					/*  OK		*/
typedef enum s_state_ok {
	initial_ok, middle_ok, final_ok
	};
 
typedef int s_state_to;					/*  OK		*/
enum s_state_to {
	initial_to, middle_to, final_to
	};
 
typedef enum s_state_no  {				/*  NOT OK	*/
	initial_no, middle_no, final_no
	};
 
struct	{
	int m;
	int n;
	s_state_ok s;		/* s_state_ok works, s_state_no fails 	*/
	} machine_state;
 
 
main ()
{
}

----------------------------------------------------------------
  _______
||       | Stephen J. Cavrak, Jr.               BITNET:  sjc@uvmvm
 |*     |					CSNET :  cavrak@uvm
 |     /   Academic Computing Services          USENET:  cavrak@uvm-gen
 |    |    University of Vermont
 |   |     Burlington, Vermont 05405
 ----

limes@sun.uucp (Greg Limes) (04/30/88)

In article <823@uvm-gen.UUCP> cavrak@uvm-gen.UUCP (Steve Cavrak) writes:
>/*  The "_ok" declaration is usable in the struct definition AND	*/
>/*  the "_to" declaration is usable, BUT				*/
>/*  the "_no" declaration generates a syntax error.			*/
>typedef int s_state_ok;				/*  OK		*/
>typedef enum s_state_ok {
>	initial_ok, middle_ok, final_ok
>	};
> 
>typedef int s_state_to;				/*  OK		*/
>enum s_state_to {
>	initial_to, middle_to, final_to
>	};
> 
>typedef enum s_state_no  {				/*  NOT OK	*/
>	initial_no, middle_no, final_no
>	};
> 
>struct	{
>	int m;
>	int n;
>	s_state_ok s;		/* s_state_ok works, s_state_no fails 	*/
>	} machine_state;

Small change. The identifier between "enum" and "{" is only an
enumerator tag, not a type definition; since enumeration tags and type
definitions can never occur in the same place, the compiler can keep
separate lists and search only the proper list.  note that the only
difference between "s_state_ok" and "s_state_no" is whether they appear
as the target of a "typedef" statement. To make it all a bit more
standard, you might consider making the types analogous to the
enumeration tags, as follows:

	typedef enum s_state_ok {
	    initial_ok, middle_ok, final_ok 
	} s_state_ok;

	typedef enum s_state_to { 
	    initial_to, middle_to, final_to 
	} s_state_to;

	typedef enum s_state_no {
	    initial_no, middle_no, final_no 
	} s_state_no;

	struct {
	    int m;
	    int n;
	    s_state_no s;
	} machine_state;

Strictly speaking, the enumeration tags are not needed, unless you want
to later use them like
	enum s_state_no	foo;
which could in fact now be written as
	s_state_no foo;

Hope this clears things up a bit.
-- 
   Greg Limes [limes@sun.com]				frames to /dev/fb

wes@obie.UUCP (Barnacle Wes) (05/02/88)

In article <823@uvm-gen.UUCP>, cavrak@uvm-gen.UUCP (Steve Cavrak) writes:
| Can someone explain why the following uses (abuses?) of typdef and enum
|
|a) typedef int s_state_ok;				/*  OK		*/
|b) typedef enum s_state_ok {
| 	initial_ok, middle_ok, final_ok
| 	};
|  
|c) typedef int s_state_to;				/*  OK		*/
|d) enum s_state_to {
| 	initial_to, middle_to, final_to
| 	};
|  
|e) typedef enum s_state_no  {				/*  NOT OK	*/
| 	initial_no, middle_no, final_no
| 	};

Your problem lies mainly with your typedef and enum syntax.  Remember
that the name following the keyword `enum' is an _enumeration type
tag_ (like a structure tag), not a variable declaration.  The syntax
for typedef is to write the keyword typedef, followed by a valid C
variable declaration.  The name that would normally become the
variable becomes the new type name.

The enum statement looks like:
	enum enum_type_tag { element, [elements...] } variable;

The typedef statement looks like:
	type valid_c_variable_declaration;
where the variable becomes the new type name.

What your code above is actually doing is declaring:
a) a new type, s_state_ok, which is int.
b) a new enumeration type, which is called s_state_ok (but no
variables of this type are declared).
c) a new type, s_state_to, which is int.
d) a new enumeration type, which is called s_state_to (again no
variables of this type are declared).
e) a non-working typedef - no variable was included in the 'enum...'
statement, so no type name could be found.

I think what you may want is:

typedef enum { initial_ok, middle_ok, final_ok } s_state_ok ;
typedef enum { initial_to, middle_to, final_to } s_state_to ;
typedef enum { initial_no, middle_no, final_no } s_state_no ;

-- 
    /\              -  "Against Stupidity,  -    {backbones}!
   /\/\  .    /\    -  The Gods Themselves  -  utah-cs!uplherc!
  /    \/ \/\/  \   -   Contend in Vain."   -   sp7040!obie!
 / U i n T e c h \  -       Schiller        -        wes

throopw@xyzzy.UUCP (Wayne A. Throop) (05/02/88)

> cavrak@uvm-gen.UUCP (Steve Cavrak)
> Can someone explain why the following uses (abuses?) of typdef and enum
> create problems [...]
> typedef int s_state_ok;
> typedef enum s_state_ok {
> 	initial_ok, middle_ok, final_ok
> 	};

Saying
        typedef enum foo {a, b, c};

is about like saying
        typedef int;
or      typedef struct foo {int a;int b;int c};

In none of these three cases has a new type name been introduced.
Presumably what was meant was

        typedef enum {
                initial_ok, middle_ok, final_ok
                } s_state_ok;

The first line where s_state_ok is typedef'ed to be an (int) is not
necessary (or legal, or wanted) once it has correctly been coined as an
enum type.

--
You can lead a yak to water but you can't teach an old dog to make a
silk purse out of a pig in a poke.
                                        --- Opus
-- 
Wayne Throop      <the-known-world>!mcnc!rti!xyzzy!throopw