Home > Blockchain >  sizeof(enum) not behaving as expected
sizeof(enum) not behaving as expected

Time:10-14

I am compiling following code using gcc for 32-bit arm mcu.

    static int test_sanity_enum_size(void)
{
    enum smallchoices { sa, sb, sc };
    enum medchoices { ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml };
    enum largechoices {
        a01, b01, c01, d01, e01, f01, g01, h01, i01, j01,
        a02, b02, c02, d02, e02, f02, g02, h02, i02, j02,
        a03, b03, c03, d03, e03, f03, g03, h03, i03, j03,
        a04, b04, c04, d04, e04, f04, g04, h04, i04, j04,
        a05, b05, c05, d05, e05, f05, g05, h05, i05, j05,
        a06, b06, c06, d06, e06, f06, g06, h06, i06, j06,
        a07, b07, c07, d07, e07, f07, g07, h07, i07, j07,
        a08, b08, c08, d08, e08, f08, g08, h08, i08, j08,
        a09, b09, c09, d09, e09, f09, g09, h09, i09, j09,
        a10, b10, c10, d10, e10, f10, g10, h10, i10, j10,
        xxx };

    /* Enum size */
    if (!TEST_size_t_eq(sizeof(enum smallchoices), sizeof(int))
        || !TEST_size_t_eq(sizeof(enum medchoices), sizeof(int))
        || !TEST_size_t_eq(sizeof(enum largechoices), sizeof(int)))
        return 0;
    return 1;
}

The functions returns 0. While all the 3 enums have only few elements so by default the enum types will be int types so I am expecting the function to return 1 but it returns 0. Do I need to modify the test condition or the enum arrays so that the function returns 1?

CodePudding user response:

You write ...

While all the 3 enums have only few elements so by default the enum types will be int types

... but although enum types are integer types, it is not safe to conclude that they are compatible specifically with int. On the contrary, the language specification says this:

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.

(C17 6.7.2.2/4)

None of your enums has too many constants or constants with too large a value for them to be made compatible with char, so the full range of types is available for the implementation to choose.

Do I need to modify the test condition or the enum arrays so that the function returns 1?

There are no arrays there, but I suppose you mean the enumerator lists in the enum definitions. There is no way to ensure that your enum types will be compatible with int in every C implementation, but you have a fairly good chance of getting int-size enums by specifying a range of enumerator values that require at least that large a representation. For example,

    enum smallchoices { sa, sb, sc = INT_MAX };
    enum medchoices { ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml = INT_MAX };
    enum largechoices {
        a01, b01, c01, d01, e01, f01, g01, h01, i01, j01,
        a02, b02, c02, d02, e02, f02, g02, h02, i02, j02,
        a03, b03, c03, d03, e03, f03, g03, h03, i03, j03,
        a04, b04, c04, d04, e04, f04, g04, h04, i04, j04,
        a05, b05, c05, d05, e05, f05, g05, h05, i05, j05,
        a06, b06, c06, d06, e06, f06, g06, h06, i06, j06,
        a07, b07, c07, d07, e07, f07, g07, h07, i07, j07,
        a08, b08, c08, d08, e08, f08, g08, h08, i08, j08,
        a09, b09, c09, d09, e09, f09, g09, h09, i09, j09,
        a10, b10, c10, d10, e10, f10, g10, h10, i10, j10,
        xxx = INT_MAX };

In principle, an implementation could use some kind of compressed representation with that, but I am not aware of any implementation going to such lengths to save space.

CodePudding user response:

Enums are problematic because an enumerated type, the variable itself, can have implementation-defined size as long as it is large enough to hold all specified items. Something like enum smallchoices { sa, sb, sc }; can fit inside a 8 bit integer type, so it's rather common that embedded systems compilers in particular optimize it down to 8 bits. So your "sanity test" is wrong, it's in conflict with the C standard.

On the other hand, enumerated constants, these: sa, sb, sc, are guaranteed to always be of type int.

Thus if you need portable code with fixed size enums (or just 32 bit aligned chunks), then you shouldn't use enum for the actual storage, but one of the intn_t types from stdint.h (likely uint32_t in this case). You can still use typedef enum etc to create a list of constants, but just don't use that type for storage if deterministic size matters.

  • Related