Search code examples
ccastingenumsunsigned-integeriar

Casting enum definition to unsigned int


According to this SO post:
What is the size of an enum in C?
enum types have signed int type.

I would like to convert an enum definition from signed int to unsigned int.

For example, on my platform an unsigned int is 32-bits wide. I want to create an enum:

typedef enum hardware_register_e
{
    REGISTER_STATUS_BIT = (1U << 31U)
} My_Register_Bits_t;

My compiler is complaining that the above definition is out of range (which it is for a signed int).

How do I declare unsigned int enum values?

Edit 1:

  1. The preference is not to expand to 64 bits (because the code resides in an embedded system).
  2. Due to skill limitations, C++ is not allowed for this project. :-(

Edit 2:

  • Compiler is IAR Embedded Workbench for ARM7.

Solution

  • Unfortunately ISO C standard (c99 6.4.4.3) states that the enumeration constants are of type int. If you compile the above with e.g. gcc -W -std=c89 -pedantic, it will issue a warning ISO C restricts enumerator values to range of ‘int’ [-pedantic]. Some embedded compilers may not accept the code at all.

    If your compiler is of the pickier variety, you can workaround the issue by using

    typedef enum hardware_register_e
    {
        REGISTER_STATUS_BIT = -2147483648   /* 1<<31, for 32-bit two's complement integers */
    } hardware_register_t;
    

    but it works correctly only if int is 32-bit two's complement type on your architecture. It is on all 32-bit and 64-bit architectures I have ever used or heard of.

    Edited to add: ARM7 uses 32-bit two's complement int type, so the above should work fine. I only recommend you keep the comment explaining that the actual value is 1<<31. You never know if somebody ports the code, or uses another compiler. If the new compiler issues a warning, the comment on the same line should make it trivial to fix. Personally, I'd wrap the code in a conditional, perhaps

    typedef enum hardware_register_e
    {
    #ifdef __ICCARM__
        REGISTER_STATUS_BIT = -2147483648   /* 1<<31, for 32-bit two's complement integers */
    #else
        REGISTER_STATUS_BIT = 1 << 31
    #endif
    } hardware_register_t;