For a conforming compiler, an enumerated constant is always of type int
(equivalently, signed int
). But such constants aren't typically stored in memory, so their type probably won't have much effect on memory requirements.
A declared object of the enumerated type is of the enumerated type itself, which is compatible with char
or with some signed or unsigned integer type. The choice of type is implementation-defined (i.e., the compiler gets to choose, but it must document how it makes the choice); the only requirement is that the type has to be capable of storing the values of all the constants.
It's admittedly odd that the constants are of type int
rather than the enumerated type, but that's how the language is defined (the reasons are historical, and C++ has different rules).
For example, given:
enum foo { x, y, z };
enum foo obj;
obj = z;
the expression z
is of type int
and has the value 2 (just like the decimal constant 2
), but the object obj
is of type enum foo
and may be as small as one byte, depending on the compiler. The assignment obj = z;
involves an implicit conversion from int
to enum foo
(that conversion may or may not require additional code).
Some compilers may provide some non-standard way to specify the type to be chosen for an enumerated type. Some may even violate the standard in some way. Consult your compiler's documentation, print out the value of sizeof (enum foo)
, and, if necessary, examine the generated code.
It's likely that your compiler will make reasonable decisions within the constraints imposed by the language. For a compiler targeted at memory-poor embedded systems, it's particularly likely that the compiler will either choose a small type, or will let you specify one. Consult your compiler's documentation.
As Ian's answer suggests, if you want to control memory usage yourself, you can use char
or unsigned char
objects. You can still use an enum
definition to define the constants, though. For example:
enum { x, y, z }; // No tag, so you can't declare objects of this type
typedef unsigned char foo; // an enum_foo object is guaranteed to be 1 byte
foo obj = z;
Reference: section 6.7.2.2 of the C standard. The link is to a 1.7-megabyte PDF of a recent draft of the 2011 ISO C standard; this particular section hasn't changed significantly since 1989.