newb help: making sense of typedef enum...

Discussion in 'C Programming' started by Chris, May 13, 2004.

  1. Chris

    Chris Guest

    I've lurked around long enough... Time to interract =)

    I'm trying to make sense of the following. I can't quite wrap my head
    around what this is actually doing:

    -------------
    typedef enum { DOUBLE_LIST, INT_LIST } DATA_TYPE;

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

    These declarations describe the header of each of a number of sections
    of a binary file (so the assignment is to use this info to read and
    make sense of the data in a supplied data file).

    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.

    If someone could provide me with the approximate English translation
    of the above statements, I'd greatly appreciate it. /Someday/ I'll be
    a passable programmer =)

    Thanks again.
    -chris

    *-also posted on .moderated, but saw that there wasn't much recent
    activity there =)
    Chris, May 13, 2004
    #1
    1. Advertising

  2. Chris

    Chris Torek Guest

    In article <>
    Chris <> 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.
    Chris Torek, May 13, 2004
    #2
    1. Advertising

  3. Chris Torek wrote:
    > 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.


    The typedef has to come second (or combined with the type declaration)
    for enum types, since C doesn't allow forward declarations of enums.

    Jeremy.
    Jeremy Yallop, May 13, 2004
    #3
  4. Chris

    Chris Torek Guest

    >Chris Torek wrote:
    >> ... (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.


    In article <>
    Jeremy Yallop <> writes:
    >The typedef has to come second (or combined with the type declaration)
    >for enum types, since C doesn't allow forward declarations of enums.


    Oops, right:

    % cat t.c
    typedef enum zorg zorg_t;
    enum zorg { A_BIT_EVIL, SOMEWHAT_EVIL, VERY_EVIL, BLOTTO };

    zorg_t obj;
    % cc -ansi -pedantic -c t.c
    t.c:1: warning: ANSI C forbids forward references to `enum' types

    GNUC allows this sort of thing as an extension, and there is no
    fundamental reason ANSI C has to forbid it, but it does.

    (It also does not help that I wrote the original posting in two or
    three parts, and then moved some of the parts around, between other
    work-related tasks. :) )
    --
    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.
    Chris Torek, May 15, 2004
    #4
  5. Chris

    Ben Pfaff Guest

    Chris Torek <> writes:

    > Oops, right:
    >
    > % cat t.c
    > typedef enum zorg zorg_t;
    > enum zorg { A_BIT_EVIL, SOMEWHAT_EVIL, VERY_EVIL, BLOTTO };
    >
    > zorg_t obj;
    > % cc -ansi -pedantic -c t.c
    > t.c:1: warning: ANSI C forbids forward references to `enum' types
    >
    > GNUC allows this sort of thing as an extension, and there is no
    > fundamental reason ANSI C has to forbid it, but it does.


    It probably wouldn't be too useful to allow forward references to
    `enum's. It's useful for struct and union types, because they
    are often referred to through pointers, but pointers to enum
    types are relatively rare. If all enums were the same width,
    then forward references would be more useful, but that would be
    an additional change in the language.
    --
    "It would be a much better example of undefined behavior
    if the behavior were undefined."
    --Michael Rubenstein
    Ben Pfaff, May 15, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. qazmlp

    typedef enum

    qazmlp, Jul 2, 2003, in forum: C++
    Replies:
    2
    Views:
    453
    Alexander Terekhov
    Jul 2, 2003
  2. Fao
    Replies:
    6
    Views:
    539
    gooch
    Jan 27, 2005
  3. oor
    Replies:
    0
    Views:
    1,334
  4. rubyrus
    Replies:
    3
    Views:
    482
    Malte Milatz
    Feb 28, 2006
  5. Randy General
    Replies:
    0
    Views:
    75
    Randy General
    Jul 8, 2009
Loading...

Share This Page