Optimizing Program Size in Embedded C/C++ Development: Structure Optimization

Optimizing Program Size in Embedded C/C++ Development: Structure Optimization

In <span>C</span> and <span>C++</span> programming, the memory layout of structures (<span>struct</span>) has a significant impact on program performance and memory usage, especially in embedded development where <span>RAM</span> is limited to <span>16K</span>, <span>8K</span>, or even <span>4K</span>; every byte counts, and there is no room for waste. This article will detail how to optimize the memory layout of structures to reduce program size and improve efficiency and performance by understanding alignment requirements, padding, and structure reordering techniques.

1. Alignment Requirements

The compiler is constrained by alignment requirements when laying out basic data types in memory to speed up memory access. These constraints lead to similar layouts across architectures such as <span>Intel</span>, <span>ARM</span>, and <span>RISC-V</span>. Except for the <span>char</span> type, other basic <span>C</span> language data types have alignment requirements. For example, a <span>short</span> of <span>2</span> bytes must start at an even address, a <span>4</span>-byte <span>int</span> or <span>float</span> must start at an address that is a multiple of <span>4</span>, and an <span>8</span>-byte <span>long</span> or <span>double</span> must start at an address that is a multiple of <span>8</span>. This self-aligning property makes memory access faster.However, it also leads to additional memory overhead—padding.

2. Padding

Padding refers to the extra bytes added by the compiler between structure members or at the end of the structure to meet alignment requirements. For example, consider the following structure (on a <span>64</span>-bit system):

struct foo1 {
    char *p;     /* 8 bytes */
    char c;      /* 1 byte */
    long x;      /* 8 bytes */
};

In this structure, the <span>char</span> type member <span>c</span> requires an additional <span>7</span> bytes of padding to ensure that the <span>long</span> type member <span>x</span> starts at an <span>8</span>-byte aligned address:

struct foo1 {
    char *p;     /* 8 bytes */
    char c;      /* 1 byte */
    //char pad[7]; /* 7 bytes padding */
    long x;      /* 8 bytes */
};

This padding, while ensuring fast access to data, also leads to memory waste.

3. Structure Alignment and Padding

Structure alignment is typically based on the width of its widest member. For instance, if a structure contains a <span>long</span> type member, the entire structure will have <span>8</span> bytes of alignment. This means the address of the structure matches the address of its first member, with no preceding padding. However, there may be trailing padding at the end of the structure to ensure the next structure instance starts at the correct aligned address.

4. Bit Fields

Bit fields allow you to declare fields in a structure that are smaller than the width of a character, as small as <span>1</span> bit. For example:

struct foobits {
    short s;
    char c;
    int flip:1;
    int nybble:4;
    int septet:7;
};

The layout of bit fields is subject to the <span>C</span> standard’s constraints; they cannot cross storage unit boundaries. <span>C99</span> guarantees that bit fields will be packed as tightly as possible, while <span>C++14</span> relaxed this constraint, allowing bit fields to span multiple allocation units.

5. Structure Reordering

From the rules of alignment and padding learned above, we can reduce padding and optimize memory layout by reordering structure members. Typically, arranging members in descending order of alignment requirements can reduce padding. For example, placing pointer-aligned members first, followed by <span>4</span>-byte <span>int</span>, then <span>2</span>-byte <span>short</span>, and finally <span>char</span> type members. This method can significantly reduce the overall size of the structure, thereby improving memory usage efficiency.

6. Practical Applications of Structure Optimization

Consider a complex structure that contains various types of data members:

struct complex {
    char c1;
    int i1;
    short s1;
    long l1;
    char c2;
};

In this structure, there will be padding between <span>c1</span> and <span>c2</span>, as well as at the end of <span>l1</span>. By reordering the members, we can reduce padding:

struct complex {
    long l1;
    int i1;
    short s1;
    char c1;
    char c2;
};

This reordered structure has only <span>4</span> bytes of padding between <span>l1</span> and <span>i1</span>, because <span>i1</span> needs <span>4</span> bytes of alignment. There is no padding between <span>c1</span> and <span>c2</span> because <span>c1</span> is already within the padding of <span>i1</span>.

For optimization comparison, the demo source code repository can be found at the end of the article:Optimizing Program Size in Embedded C/C++ Development: Structure Optimization

Conclusion

Understanding and applying structure optimization techniques is crucial for improving the performance and memory efficiency of <span>C</span> and <span>C++</span> programs. By grasping alignment requirements, padding, and structure reordering, developers can design more efficient and compact data structures, thereby enhancing overall program performance while maintaining code readability. Remember, optimizing structures is not just about reducing memory usage; it can also speed up program execution, especially when handling large amounts of data or in memory-constrained environments.

The article is accompanied by a demo source code repository: Structure Optimization Comparison demo [https://gitee.com/icemaple/windsurfdemo/tree/structsize/]

By the way, a book giveaway event was launched on New Year’s Day, and today (January 6th at 6:06 PM) is the draw. Interested friends can reply in the background to get the lottery link~Wishing everyone a year of <span>666</span> ~

Related Reading:1. New Harmony Next in 2025, new open-source Harmony, new Flutter, new lottery—no bugs all year2. Updated MDK Embedded Development Experience: The ‘Not’ Perfect Combination Guide of VS Code + KEIL

3. Windows + vscode + cmake + gtest: C++ unit testing scheme using VSCode editing and CMake building and running on Windows

Leave a Comment