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
2010-01-29 12:17:51
Is that cast to int really needed? In C enums are always of type int.
Maurits Rijk
2010-01-29 12:21:47
Probably not - I'll change it.
anon
2010-01-29 12:23:18
@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
2010-01-29 12:29:37
@Johannes Aren't some standard conversions performed on variadic parameters?
anon
2010-01-29 12:43:31
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
2010-01-29 12:52:58
@Johannes OK - I'll leave the code as it stands, as your comments are informative, as usual.
anon
2010-01-29 12:55:58
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
2010-01-29 12:58:52
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
2010-01-29 13:21:07
Johannes Schaub - litb
2010-01-29 13:44:23
+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
2010-01-29 12:18:04
This (of course) implies that your enum really starts at 0 and is consecutive without "holes".
unwind
2010-01-29 12:24:45
+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
2010-01-29 12:21:25
@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
2010-01-29 13:15:53
@Johannes, from my knowledge, you are right. thanks for the clear explanation !
Matthieu
2010-01-29 16:15:53
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
2010-01-29 13:16:36
+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
2010-01-29 13:41:58