3

In http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0065d/Cihejcda.html there is an option and a note:

Enum container always int

Select this option to force all enumerations to be stored in integers. By default, the compiler uses the smallest data type that can hold all values in an enum.

Note
This option is not recommended for general use and is not required for ANSI-compatible source. If used incorrectly, this option can cause errors in the resulting image.

What is an example in C of such an incorrect use?


Background:

I'm developing an embedded application in C an removing this compiler flag fixed an error (or only the symptoms of another error). The error was an

sprintf(big_enought_char_array, "%4.1f", float_var)

function call wasn't correctly formatting floats.

This was almost fixed by using the right alignment for the memory used as stack. "Almost" fixed because the content of the array was ok, but the decimal point had the wrong char. Removing the compiler option mentioned above fixed the problem. So the question is what is this compiler option doing exactly and what is an incorrect use of it?

Community
  • 1
  • 1
memic
  • 73
  • 8
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a [mcve]. – too honest for this site Oct 27 '15 at 11:55
  • Floats are not connected to enums. So there seems to be another effect involved. – too honest for this site Oct 27 '15 at 11:55

3 Answers3

3

I assume you are referring to this option:

Enum container always int

Select this option to force all enumerations to be stored in integers. By default, the compiler uses the smallest data type that can hold all values in an enum.

In C the type used for an enumerated type is implementation-defined (but the enum constant are always int): it's an integer type that can represent all the enum constants.

If you set the type for enumerated type to int there are two issues that I can think of:

1) if you make your program rely on the fact that enum are int (for example assuming sizeof is the same as sizeof (int)), it is not portable on other systems

2) if you define a constant with a value larger than INT_MAX (or that an int cannot represent), say for example UINT_MAX, your type will not be able to represent it where C enum are guaranteed to represent it.

Regarding your specific issue with the sprintf call, it seems totally unrelated with this option. You are probably invoking some undefined behavior before your call.

ouah
  • 142,963
  • 15
  • 272
  • 331
1

what is this compiler option doing exactly

Well, normally your average enum doesn't have e.g. 2³² entries -- in most cases, it doesn't even have 256. In that case, the C compiler normally is free to use a shorter representation of the value, e.g. a single byte.

Using that flag will make all enums occupy the same, int sized (read: word-length) memory. That's only in a couple of pretty special cases, and obviously, it breaks sprintf; I don't think that's a usual thing to happen, so: what libc implementation are you using? Make sure it doesn't explicitly forbid usage of that flag, and file a bug report if necessary. Make a minimal test case to demonstrate the issue.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • Why does it *obviously break sprintf*? – Déjà vu Oct 27 '15 at 11:04
  • 1
    @ringø: Marcus means "evidently", "as can be observed", rather than "it stands to reason". – Jongware Oct 27 '15 at 11:11
  • or not use `sprintf` all-together :) – Tomer W Oct 27 '15 at 11:24
  • im using the embeeded versions of sprintf() shipped with the armcc compiler from keil. i tried an minimal test case, but im unable to reproduce it so far without my embedded realtime os running. so assume that something destroys my lookup table used in the sprintf function - if there is used one in the implementation. – memic Oct 27 '15 at 12:16
  • 1
    @TomerW He doesn't either, that's why he's wondering why the behavior changes when the compiler flag is set (I'm guessing) – Russ Schultz Oct 27 '15 at 13:00
  • 1
    @Russ Schultz: exactly – memic Oct 27 '15 at 13:39
0

Here's my guess with regards to sprintf():

Your stack was actually declared as a char[] array, and it was amomg some enum variables or was in a __packed structure. Changing the enum from a char to a int (or the other way around) changed the alignment of the stack variables bringing the float into alignment. (the 3rd variable of sprintf() being a float will almost certainly end up being passed on the stack)

The ARM requires the stack to be 8 byte aligned. Best to declare it as uint64_t (and definitely not in a __packed structure) so its alignment is always right.

Russ Schultz
  • 2,545
  • 20
  • 22