itmanwork
itmanwork

Reputation: 121

c using enum inside struct

I would like to create enum and structs in c. However, I need the enum to be inside another struct (to avoid duplicating the name). Something like this:

#include <stdio.h>

// define structure as our enum namespace
typedef struct {
    typedef enum {
        Host,
        Cookie,
        Agent
    } Name;
} header_n;

typedef struct {
    header_n::Name key; // using top enum
    char value[128];
} header_t;

int main() {

    header_t header;
    header.key = header_n::Agent;

    return 0;
}

In fact, I want to use struct for my enum and then use that enum as a separate type in another structure and then call the last structure as a complete type but I get these errors:

error: expected specifier-qualifier-list before 'typedef'
     typedef enum {

error: expected expression before ':' token
     header_n::Name key; // using top enum

error: bit-field '<anonymous>' width not an integer constant
     header_n::Name key; // using top enum

error: bit-field '<anonymous>' has invalid type

error: 'header_t {aka struct <anonymous>}' has no member named 'key'
     header.key = header_n::Agent;

error: expected expression before 'header_n'
     header.key = header_n::Agent;

Upvotes: 12

Views: 33325

Answers (2)

klutt
klutt

Reputation: 31356

This is simply not possible. The C language does not support it. C requires you to do all type declarations in global space. Or to be more precise: The C standard does not require type declarations to work in non-global space.

So you simply have to choose different name for them. You can emulate the namespace feature in C++ to by naming the types in a certain way to accomplish basically the same thing. Something like this:

typedef enum {
...
} foo_name;

typedef struct {
    foo_name name;
} foo;

typedef enum {
...
} bar_name;

typedef struct {
    bar_name name;
} bar;

typedef struct {
    bar_name name;
    foo_name name;
} foobar;

Upvotes: 11

John Bode
John Bode

Reputation: 123458

Several things:

  1. structs in C are nothing more than collections of data - they have no "smarts" to them.
  2. You cannot use typedef within a struct definition;
  3. A struct definition in C does not create a new namespace;
  4. C provides 4 namespaces - one for struct, union, and enum tags, one for struct and union members, one for statement labels, and one for all other identifiers (variable names, function names, typedef names, enumeration constants, etc.). There are no user-defined namespaces, and there's no :: scoping operator in C.

You will either have to define your enumeration types separately from the struct types:

typedef enum { Host, Cookie, Agent } Name;

typedef struct {
  Name key;
  char value[128]
} header_t;

or, use a non-typedef'd enum within the struct definition:

typedef struct
{
  enum key_t { Host, Cookie, Agent } key;
  char value[128];
} header_t;

int main( void )
{
  header_t header;
  header.key = Agent;
  ...
}

Even though we defined the type within the header_t type, enum key_t can be used outside of it; C doesn't limit the use of the key_t tag to just header_t (again, struct definitions do not create a new namespace). So it's possible to do this:

typedef struct
{
  enum key_t { Host, Cookie, Agent } key;
  char value[128];
} header_t;

int main( void )
{
  header_t header;
  header.key = Agent;
  enum key_t some_other_key = Cookie;
  ...
}

You can leave off the key_t tag:

typedef struct
{
  enum { Host, Cookie, Agent } key;
  char value[128];
} header_t;

so you can't define a new instance of that enumeration type outside of the struct, but you can still use the enumeration constants Host, Cookie, and Agent after this definition and assign them to an integer object:

int keyval = Host;

Since enumeration constants share the "all other identifiers" namespace, no two enum types can use the same enumeration constants between them; you can't do something like

typedef enum { foo, bar, bletch } EnumType1;
typedef enum { bletch, foo, bar } EnumType2;

The compiler will complain that each of bletch, foo, and bar in the second enum definition have already been defined. If you want to use the same names between two different enumeration types, you'll have to create unique prefixes or suffixes for them:

typedef enum { T1_foo, T1_bar, T1_bletch } EnumType1;
typedef enum { T2_bletch, T2_foo, T2_bar } EnumType2;

Upvotes: 14

Related Questions