8

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;
d-cubed
  • 1,034
  • 5
  • 30
  • 58
itmanwork
  • 81
  • 1
  • 1
  • 7
  • 1
    You can not create a type-name (using `typedef`) nested inside structures. All types are *global* and as such type-names must be defined in the global (file) scope. C is not C++. Please [get a couple of good beginners books to read](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) instead of just guessing about syntax. – Some programmer dude Jan 12 '18 at 12:23
  • yes i know about C .... but is there any way to define enum in that structure (only on that struct scope) and then call it like up? – itmanwork Jan 12 '18 at 12:25
  • No it's not possible. C doesn't have nested structural scopes like that. – Some programmer dude Jan 12 '18 at 12:26
  • 3
    This code looks like C++ code. – Jabberwocky Jan 12 '18 at 12:26
  • of for what i want to do (header_t header; header.key = header_n::Agent;) what is your suggestion? it's must be a way at all for this ! i just want to hide my enum items inside a scope and avoid from duplication.... what is your suggestion? – itmanwork Jan 12 '18 at 12:27
  • 4
    If you want to continue to program in C, then the answer is still no. It's just not possible. Perhaps if you take some time to ask us about the *real* problem you have, the reason *why* you want to use a solution like this, then we might be able to help you with that instead. Please [read about the XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), as well as [the help pages](http://stackoverflow.com/help). Also please [take the tour](http://stackoverflow.com/tour) and [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask). – Some programmer dude Jan 12 '18 at 12:29
  • Is there a reason you can't create a `typdef` for the `enum` and then use that in both `struct`s? – DavidH Jan 12 '18 at 12:30
  • so when you want to create new C program and you have 2 enum with same items names, what do you do? – itmanwork Jan 12 '18 at 12:31
  • 2
    You mean you have two different enumerations, both using the same name for one of their values? Then you have to rename one of them. Or use things like prefixes or suffixes to make the names more unique. That's the only solution to that problem. – Some programmer dude Jan 12 '18 at 12:32
  • Just stop using the typdefs. This is C. – Jonathon Reinhart Jan 12 '18 at 12:35
  • 1
    It looks like you are trying to mix C and C++ here. the `::` construct **is** C++ not C. Even if C++ is *based* on C they are indeed different languages, and any single compilation unit (source file) can use only one. – Serge Ballesta Jan 12 '18 at 13:01

2 Answers2

12

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;
John Bode
  • 119,563
  • 19
  • 122
  • 198
9

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;
klutt
  • 30,332
  • 17
  • 55
  • 95
  • you mean it's not true too ? typedef struct header_n { enum Names { Host, Cookie, Agent }; } header_n; i didn't get any error from this ... is it possible to build what i want using this ? – itmanwork Jan 12 '18 at 13:01
  • Prefixes are more straighforward than namespaces. You have `_` instead of `::` and you don't need to declare anything more than the bare necessities. – mouviciel Jan 12 '18 at 13:04
  • but using prefix, getting my enum names (inside items) very long – itmanwork Jan 12 '18 at 13:10
  • 1
    @itmanwork You can declare an enum instance inside a struct, but you cannot use typedef. So what you want to do is impossible. – klutt Jan 12 '18 at 13:24
  • 2
    The bottom line is basically this: If this feature is extremely important to you, then don't use C. – klutt Jan 12 '18 at 13:26