tags:

views:

674

answers:

5

Is there a one-liner that lets me output the current value of an enum?

+1  A: 
enum A { foo, bar } a;
a = foo;
printf( "%d", a );   // see comments below
anon
Is that cast to int really needed? In C enums are always of type int.
Maurits Rijk
Probably not - I'll change it.
anon
@Maurits, @Neil, That cast is needed. Enumeration variables are of a distinct type, and are compatible with *some* integral type being able to store all the values of the enumerators. That's not necessarily type `int`. (An enumeration variable may be compatible with `long`, for instance, just fine). printf's `%d` however wants *exactly* type `int`, so a cast is best to do, i think. Only the enumerators (the one in the list in the declaration) are exactly of type `int`.
Johannes Schaub - litb
@Johannes Aren't some standard conversions performed on variadic parameters?
anon
Well, these "default argument promotions" happen for "expressions with integer types whose conversion rank is less than or equal the rank of int and unsigned int". Anyway, the conversion rank of enumerations are defined at 6.3.1.1/1 as being "equal to the rank of the compatible integer type". If that compatible type is `long` or something, then no default promotion happens.
Johannes Schaub - litb
@Johannes OK - I'll leave the code as it stands, as your comments are informative, as usual.
anon
Notice that an enumeration is also an integer type (as opposed to C++, where they are not), but the compatible type chosen above must not be an enumeration type, because it says that it must be a "signed integer type or an unsigned integer type" neither of which enumerations are. So i should have said above that "some signed/unsigned integral type or char" is chosen, i think :) This matter is like `bool` or `char` in C++, that are integer types, but neither a "signed integer" one nor an "unsigned integer" (even tho `char` is either signed or unsigned). Matter is a bit complicated, i think -.-
Johannes Schaub - litb
Now I start to get confused. From this discussion (and Wikipedia, MSDN, etc.) I get the impression that the enum expression is always of type int. The underlying type can differ and can be char, int, long, etc. So printf("%d", a) is potentially dangerous while printf("%d", C_ENUM_VALUE) would be safe?
Maurits Rijk
Johannes Schaub - litb
+8  A: 

As a string, no. As an integer, %d.

Unless you count:

static char*[] enumStrings = { /* filler 0's to get to the first value, */
                               "enum0", "enum1", 
                               /* filler for hole in the middle: ,0 */
                               "enum2", .... };

...

printf("The value is %s\n", enumStrings[thevalue]);

This won't work for something like an enum of bit masks. At that point, you need a hash table or some other more elaborate data structure.

bmargulies
This (of course) implies that your enum really starts at 0 and is consecutive without "holes".
unwind
+4  A: 
enum MyEnum
{  A_ENUM_VALUE=0,
   B_ENUM_VALUE,
   C_ENUM_VALUE
};


int main()
{
 printf("My enum Value : %d\n", (int)C_ENUM_VALUE);
 return 0;
}

You have just to cast enum to int !
Output : My enum Value : 2

Matthieu
enums _are_ ints.
aib
@aib, it's easy to overlook when to cast and when not, though. What do you mean by "enums"? I would always do the cast. In the above the cast is redundant, because it's using the enumerator. But if he had done `enum MyEnum c = C_ENUM_VALUE;` and then passing `c`, he would need the cast. See discussion below on @Neil's answer.
Johannes Schaub - litb
I see. This is right, then.
aib
@Johannes, from my knowledge, you are right. thanks for the clear explanation !
Matthieu
A: 

The correct answer to this has already been given: no, you can't give the name of an enum, only it's value.

Nevertheless, just for fun, this will give you an enum and a lookup-table all in one and give you a means of printing it by name:

main.c:

#include "Enum.h"

CreateEnum(
        EnumerationName,
        ENUMValue1,
        ENUMValue2,
        ENUMValue3);

int main(void)
{
    int i;
    EnumerationName EnumInstance = ENUMValue1;

    /* Prints "ENUMValue1" */
    PrintEnumValue(EnumerationName, EnumInstance);

    /* Prints:
     * ENUMValue1
     * ENUMValue2
     * ENUMValue3
     */
    for (i=0;i<3;i++)
    {
        PrintEnumValue(EnumerationName, i);
    }
    return 0;
}

Enum.h:

#include <stdio.h>
#include <string.h>

#ifdef NDEBUG
#define CreateEnum(name,...) \
    typedef enum \
    { \
        __VA_ARGS__ \
    } name;
#define PrintEnumValue(name,value)
#else
#define CreateEnum(name,...) \
    typedef enum \
    { \
        __VA_ARGS__ \
    } name; \
    const char Lookup##name[] = \
        #__VA_ARGS__;
#define PrintEnumValue(name, value) print_enum_value(Lookup##name, value)
void print_enum_value(const char *lookup, int value);
#endif

Enum.c

#include "Enum.h"

#ifndef NDEBUG
void print_enum_value(const char *lookup, int value)
{
    char *lookup_copy;
    int lookup_length;
    char *pch;

    lookup_length = strlen(lookup);
    lookup_copy = malloc((1+lookup_length)*sizeof(char));
    strcpy(lookup_copy, lookup);

    pch = strtok(lookup_copy," ,");
    while (pch != NULL)
    {
        if (value == 0)
        {
            printf("%s\n",pch);
            break;
        }
        else
        {
            pch = strtok(NULL, " ,.-");
            value--;
        }
    }

    free(lookup_copy);
}
#endif

Disclaimer: don't do this.

Al
+1  A: 

Some dude has come up with a smart preprocessor idea in this post

http://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c

BlueTrin