Understanding Enum Size and Alignment in C

Understanding -fshort-enums in C

When working with enumerations (enum) in C, it’s easy to assume they are always 4 bytes, just like int. However, compilers offer optimization flags like -fshort-enums that can reduce memory usage by adjusting enum sizes based on the range of their values.

In this post, we’ll explore how -fshort-enums affects enum size, element size, and variable size through explanation and example.


🔍 What Does -fshort-enums Do?

By default, the C compiler treats all enum types as int, which typically means 4 bytes of memory regardless of the values they store. The GCC flag -fshort-enums changes this behavior:

With -fshort-enums, the compiler chooses the smallest integer type (starting from 1 byte) that can represent all the enum values.


📐 Explanation with -fshort-enums

  • Enum Type Size: The size of the enum type itself is minimized.
    • For Enum_8bit, values range from 1–4 → 1 byte.
    • For Enum_16bit, values are within 16-bit range → 2 bytes.
  • Enum Element Size: Each enum element like CAN1, IP4, or VP3 is treated as an int, which is 4 bytes, unless the value itself demands a larger type (e.g., 64-bit values).

  • Enum Variable Size: The actual variable holding the enum takes up memory based on the enum’s underlying type (1, 2, or 4 bytes), not necessarily the element size.

🧪 Code Example: Exploring Enum Sizes

#include<stdio.h>                                                                                                                   

typedef enum {
    CAN1 = 1,
    CAN2,
    CAN3,
    CAN4,
} Enum_8bit;

typedef enum {
    IP4 = 0x1234,
    IP5 = 0x444,
    IP6 = 0xffee,
} Enum_16bit;

typedef enum {
    VP1 = 0x1234,
    VP2 = 0x444,
    VP3 = 0xffeeEEEEEEEEEDDE,
} Enum_32bit;

void main(void) {
    printf("Enum_8bit is %lu.\n", sizeof(Enum_8bit));  
    printf("Enum_16bit is %lu.\n", sizeof(Enum_16bit));
    printf("Enum_8bit element is %lu.\n", sizeof(CAN1));   
    printf("Enum_16bit element is %lu.\n", sizeof(IP4));   
    printf("Enum_32bit 64bits element is %lu.\n", sizeof(VP3));   
    printf("Enum_32bit 16bits element is %lu.\n", sizeof(VP2));   
    
    Enum_16bit bit16 = IP4;
    Enum_8bit bit8 = CAN1;
    printf("Enum_8bit variable is %lu.\n", sizeof(bit8));
    printf("Enum_16bit variable is %lu.\n", sizeof(bit16));
}

🛠 Compilation Results

✅ With -fshort-enums:

Enum_8bit is 1.
Enum_16bit is 2.
Enum_8bit element is 4.
Enum_16bit element is 4.
Enum_32bit 64bits element is 8.
Enum_32bit 16bits element is 4.
Enum_8bit variable is 1.
Enum_16bit variable is 2.

🚫 Without -fshort-enums:

Enum_8bit is 4.
Enum_16bit is 4.
Enum_8bit element is 4.
Enum_16bit element is 4.
Enum_32bit 64bits element is 8.
Enum_32bit 16bits element is 4.
Enum_8bit variable is 4.
Enum_16bit variable is 4.

📌 Summary

  • Default Behavior: Without any flags, enums default to 4 bytes (int) for all values.
  • Optimized with -fshort-enums:
    • Enum types are downsized to the smallest suitable integer type.
    • Enum elements still behave like int unless the value dictates otherwise.
    • Enum variables take on the type size defined by the enum type, making the optimization effective for memory footprint.
  • ⚠️ Memory Alignment: Be aware that actual size might still vary based on your platform’s architecture and data alignment rules.

💡 Why This Matters

Using -fshort-enums can significantly reduce memory usage in embedded systems, low-level drivers, or applications where space efficiency is critical. However, it may also introduce portability concerns if not carefully managed across different compilers or platforms.


打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦