Re: newb help: making sense of typedef enum...

From: Chris Torek (nospam_at_torek.net)
Date: 05/13/04


Date: 13 May 2004 05:57:43 GMT

In article <939f49f8.0405122057.56b5d67d@posting.google.com>
Chris <iamlevis3@hotmail.com> writes:
>I'm trying to make sense of the following. ...
>typedef enum { DOUBLE_LIST, INT_LIST } DATA_TYPE;

The typedef here is something of a red herring.

The best thing to do, as far as I am concerned, for understanding
purposes, is to remove all the typedefs from C code. In this case,
that also requires adding an enumeration tag, giving:

    enum list_enum { DOUBLE_LIST, INT_LIST };

This defines a new type, "enum list_enum", with two enumeration
members. The two enumeration members are just names for integer
constants, numbered sequentially starting from 0 (in this case).

All the typedef does, once it is re-inserted, is make an alias
-- another name -- for the type "enum list_enum":

    typedef enum list_enum DATA_TYPE;

Now you can type "DATA_TYPE" wherever you would otherwise have to
type "enum list_enum". (In fact, there is no requirement that the
typedef come second, and if you want to use typedefs with linked-list
structures, I recommend putting the typedef line first. I prefer
not to use typedef at all, myself, though.)

>typedef struct {
> DATA_TYPE type;
> int number_values;
>} section_t;

Here is another one of these silly mixed-up typedef lines again.
Assuming you *want* to use typedefs (for whatever strange reason),
I still claim it is better to write the typedef first, *then* the
struct declaration. Of course, you will have to add a tag, just
as before:

    typedef struct section section_t;
    struct section {
        DATA_TYPE type; /* or: enum list_enum type; */
        int number_values;
    };

Again, the typedef does not really add anything -- the "real"
type is "struct section"; "section_t" is just an alias for this,
an extra name that lets you skip the word "struct".

It is worth noting here that both "section_t" and "DATA_TYPE"
are spelled specially: the former ends in "_t", and the latter
is in all-capital-letters. When using typedefs, it *is* a good
idea to mark them specially, because they kind of goof up the
syntax of C programs. Ordinary declarations will have an
instantly recognizable keyword in front:

    int i;
    struct S somestruct;
    void f(void);
    double (d); /* unnecessary parentheses, but for illustration */

But suppose you see:

    zog (x);

Is this a declaration of the variable "x" of type "zog", where
"zog" is a typedef-alias for some other type? Or is it a call
to the function zog(), passing the value of x? If all your
typedefs are consistently marked, you can tell:

    zog_t (x); /* this one is a variable declaration */
    mog (y); /* this one is a call to a function */

In this case, one typedef uses an "_t" suffix, and the other uses
all-uppercase. It seems a bit odd to mix conventions like this.

>Now, I typed this stuff into a small program and ran it though gcc.
>gcc had no complaints, but I'm puzzled as to how, in the struct,
>DATA_TYPE can be a valid type, since in the enum there is DOUBLE_LIST
>and INT_LIST... nothing that seems like a type that a compiler would
>understand without more information.

Enumeration members are just aliases for integer constants. Even
if the enumeration does not have a tag, you can even use this to
define constants -- real, true constants, not read-only "const"
variables -- that you can use wherever you would otherwise use a
constant:

    enum { MAX_LEVELS = 30 };

    int some_table[MAX_LEVELS];

The original enumeration did not have a tag, but its type -- an
otherwise un-nameable type -- is "captured" by the surrounding
typedef:

    typedef enum /* no tag */ { MEMBER } alias;

Now "alias" is an alias for the missing enumeration tag. The
members are just integer constants, and in this case just 0 and
1 respectively. So:

    if (i == INT_LIST)

means exactly the same thing as:

    if (i == 1)

To declare i as a variable with the enumerated type, you might
normally write either:

    enum the_tag i;

or:

    alias i;

but here the tag is missing, so you have to use the typedef-alias.

-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W)  +1 801 277 2603
email: forget about it   http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.


Relevant Pages

  • Re: Set with Sort routine
    ... the struct declaration were the things that added clutter. ... typedef struct name ... I showed that omission of the tag ...
    (microsoft.public.vc.stl)
  • Re: Set with Sort routine
    ... typedef struct MyElem ... The only time you need one as part of a typedef like this is when the struct has a pointer to its own type. ... You can't use the typedef name for that, since it hasn't been defined yet, so you have to use the name of the tag, along with the struct keyword. ...
    (microsoft.public.vc.stl)
  • Re: why still use C?
    ... Use of a struct member name outside of the region that, ... name is itself a struct tag, enumeration type, or enumerator name. ... A declaration of a const variable with file scope, ... A typedef with the same name as a struct tag. ...
    (comp.lang.c)
  • Re: Set with Sort routine
    ... Even in C, you should specify a tag, e.g. ... typedef struct MyElem ... typedef like this is when the struct has a pointer to its own type. ...
    (microsoft.public.vc.stl)
  • Re: Set with Sort routine
    ... typedef struct MyElem ... The only time you need one as part of a typedef like this is when the struct has a pointer to its own type. ... You can't use the typedef name for that, since it hasn't been defined yet, so you have to use the name of the tag, along with the struct keyword. ...
    (microsoft.public.vc.stl)