Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c using enum inside struct

Tags:

c

enums

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;
like image 455
itmanwork Avatar asked Jan 12 '18 12:01

itmanwork


1 Answers

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;
like image 124
John Bode Avatar answered Sep 30 '22 11:09

John Bode