bob smith
bob smith

Reputation: 63

Accessing enum strings by array notation?

If I were to compare these enum values in a switch statement. What is the purpose of numbering the strings?

If I store the enum in a header file and then import the header file. I know that I can say events event = ls; (I can store ls into events)

But can I say something like event[0] to access ls?

#define NUM_EVENTS 11
typedef enum events {
    ls = 0,
    rs = 1,
    ws = 2,
    lo = 3,
    ro = 4,
    lc = 5,
    rc = 6,
    gru = 7,
    grl = 8,
    gll = 9,
    glu = 10
} events;

Upvotes: 0

Views: 114

Answers (4)

user2371524
user2371524

Reputation:

There's no such thing as enum strings. What you're talking about are identifiers, only used in the source code. An enum in C is represented as an integer type, typically int, but compilers are free to chose e.g. short or another one. An enum is even allowed to hold a value that doesn't correspond to one of the named members. Only these numbers go in the compiled programs. C compilers do not (have to) store any type information in the compiled executable.

So, if you need the enum identifiers as strings at runtime, you have to store them yourself. This typically looks like e.g.

typedef enum events {
    ls,
    rs,
    ws,
    lo,
    ro,
    lc,
    rc,
    gru,
    grl,
    gll,
    glu
} events;

static const char *event_names[] = {
    "ls",
    "rs",
    "ws",
    "lo",
    "ro",
    "lc",
    "rc",
    "gru",
    "grl",
    "gll",
    "glu"
};

void example(event ev)
{
    // might want to check for a valid value here ...

    // print name of event
    puts(event_names[ev]);
}

As a side note, there's no need to explicitly number the members in your case -- the default numbering starts at 0 and increases by one for each member.


Further hints:

  • enum member identifiers are global, so it's a good practice to make them unique, e.g. by prepending the type name like this:

    typedef enum events {
        event_ls,
        event_rs,
        // ...
    } events;
    
  • The above code violates the DRY (don't repeat yourself) principle: when changing the enum, you have to touch two different locations in the code which is a source of potential bugs. This is sometimes solved using X macros. There are opposing opinions whether this is good or bad style, just presenting it here for completeness:

    #define EVENTS_LIST \
        X(ls) \
        X(rs) \
        X(ws) \
        X(lo) \
        X(ro) \
        X(lc) \
        X(rc) \
        X(gru) \
        X(grl) \
        X(gll) \
        X(glu)
    
    #define X(name) event_##name ,
    typedef enum events {
        EVENTS_LIST
    } events;
    #undef X
    
    #define X(name) #name ,
    static const char *event_names[] = {
        EVENTS_LIST
    };
    #undef X
    

    after preprocessing, this produces

    typedef enum events {
        event_ls , event_rs , event_ws , event_lo , event_ro , event_lc , event_rc , event_gru , event_grl , event_gll , event_glu ,
    } events;
    
    static const char *event_names[] = {
        "ls" , "rs" , "ws" , "lo" , "ro" , "lc" , "rc" , "gru" , "grl" , "gll" , "glu" ,
    };
    

Upvotes: 1

Burstful
Burstful

Reputation: 347

If you really want to use event[0] you can do this:

events event[11];
event[0] = ls;
event[1] = rs;
event[2] = ws;
event[3] = lo;
event[4] = ro;
event[5] = lc;
event[6] = rc;
event[7] = gru;
event[8] = grl;
event[9] = gll;
event[10] = glu;

I will say though, I am sure there is a way around doing this ( since it is not elegant at all ), if you give more context :)

EDIT: After re-reading your question, I get the impression you want the STRING "ls" from your enum?

If this is so, then no you are not able to do this. Enumerated types are great for switch statements, but if you are trying to turn a variable name into a string through code without hardcoding event[0] = "ls", it isn't going to happen.

Upvotes: 0

ikegami
ikegami

Reputation: 385897

I think you are asking how to get the name of the event as a string from the event so you can do something like printf("%s\n", SOMEFUNCTION(event)); to print the name of the event.

There's is no such function.

Upvotes: 0

Zalman Stern
Zalman Stern

Reputation: 3191

You can cast from an integer to an enum, which is equivalent to indexing if the enum is a dense sequence starting at zero. In general enums are just a way to introduce symbolic names for a list of related constants. It is syntactically better than doing so using #define but there is very little functionality beyond such. If the numbers are not explicitly assigned, the compiler will manage assigning unique values to each member. But even finding the max value is not something offered by the language, much less mapping to names as strings or similar.

Upvotes: 0

Related Questions