Does defining enum type has a heavy memory imprint?

Go To StackoverFlow.com

2

I am working with embedded device, with 32K of memory, writing in plain C using IAR EWARM v6.30.

To make code more readable I would like to define some enum types, for example, something like

{RIGHT_BUTTON, CENTER_BUTTON, LEFT_BUTTON}

instead of using 0, 1, 2 values, but I am afraid it will take additional memory that is already scarce.

So I have 2 questions: 1) Can I force enum to be of short or byte type intead of int? 2) What is an exact memory imprint of defining enum type?

2012-04-04 07:29
by Flot2011


6

In fully compliant ISO C the size and type of an enum constant is that of signed int. Some embedded systems compilers deliberately do not comply with that as an optimisation or extension.

In ISO C++ "The underlying type of an enumeration is an integral type that can represent all the enumerator values defined in the enumeration.", so a compiler is free to use the smallest possible type, and most do, but are not obliged to do so.

In your case (IAR EWARM), the manual clearly states:

enter image description here

No option required, in fact you'd need to use --enum_is_int to force compliant behaviour. Other compilers may behave differently or have different extensions, pragmas or options to control this. Such things will normally be defined in the documentation.

2012-04-04 16:16
by Clifford
Thanks a lot, I didn't have the manual hand - Flot2011 2012-04-04 17:43
@Flot2011: Really!? This is the Internet; the manual is always handy! I downloaded it. I don't have the compiler, but I would imagine, having used other IAR products in the past, that that the manual is installed locally when you install the IDE, and is available from the help menu in one for or another (help or PDF) - Clifford 2012-04-04 17:55
:OK, so you want an explanation anyway. Here it goes: I do not work with this compiler at all, I am working with VS2003 and my code is later on recompiled on the client's machine, because the client doesn't want to buy a license for me :-( I have had a trial that was expired and I uninstalled it. As I was not sure which exactly version of the IAR the client will finally use I have thought that I will better ask a common question. But actually you are right, I was a bit lazy here. Thanks for the answer - Flot2011 2012-04-04 20:11
As I recall (but I may be wrong) an expired evaluation licence allows you to compile but not link, or load code to a target. If that is the case it may have been useful to retain the installation for verification that the code will at least compile and for access to documentation - Clifford 2012-04-05 09:47
I don't believe this is correct. C11 6.7.2.2 states that "The identifiers in an enumerator list are declared as constants that have type int and may appear wherever such are permitted." but also that "Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of representing the values of all the members of the enumeration."Lundin 2012-04-05 11:45
For your example from IAR, this would mean that Spade1, Spade2 etc are guaranteed to be (signed) int, but a variable of enum type Cards may be char, signed int or unsigned int - Lundin 2012-04-05 11:46
C11 is irrelevant unless you happen to be using a compiler that implements it - which very few do at present. The compiler in question is ISO/IEC 9899:1999 conformant (as per the documentation). Moreover the ISO standard can say what it likes; teh text I posted is in fact a screen-grab image of the IAR manual - I didn't make it up - Clifford 2012-04-05 17:59
But what if I want to use --enum-as-unsigned-int? This is very helpful if I use enums as bit-flags, as bit-operations are not recommended and non-MISRA:2004 compliant for int type - lkanab 2015-08-03 05:15
@lkanab : Using enums for bit-flags is probably a bad idea - if you combine two flags with | for example, you end up with an integer that is no-longer an enum value (unless you exhaustively define all possible combinations!), and certainly no longer has enum type. Use const, #define or struct bit-fields instead as appropriate. Either way - you have asked a question in a comment to a barely related issue - post a new question rather then commenting on three year old answers. By commenting on this answer, you are asking only me when you could be asking all or SO - Clifford 2015-08-03 11:12


2

If you really need to keep the data size down to a char then you can always use a set of #define constant values to represent the enum states and only ever use these values in the your assignments and tests.

2012-04-04 11:14
by uɐɪ


2

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.

2012-04-04 22:14
by Keith Thompson
This is the correct answer for C. I can verify that the standard text has not changed between the C11 draft and the official C11 standard either - Lundin 2012-04-05 11:52


1

An ANSI C compiler will always represent an enum as an int to represent variables of type enum.

http://en.wikipedia.org/wiki/Enumerated_type#C_and_syntactically_similar_languages

One option to use ints in your program would be to use them to define values, but cast to char when actually used

char value = (char)Buttons.RIGHT_BUTTON;
2012-04-04 07:34
by Eric J.
Yes, I know it, I was just hoping there is some compiler switch of the kind to change this default behaviour - Flot2011 2012-04-04 07:38
@Flot2011: Depends on your compiler. Which compiler do you use - Eric J. 2012-04-04 07:38
IAR for ARM, ver 6.3 - Flot2011 2012-04-04 13:20
@Flot2011: Read the manual - it is quite clear on this - Clifford 2012-04-04 16:18
Ads