Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Industrial Internet of Things >> Embedded

Embedded C Structures: A Practical Guide to Definition, Usage, and Memory Optimization

Structures are a cornerstone of efficient embedded C programming. In this article, we’ll explore their practical applications, the syntax for declaring them, and the impact of data alignment on memory usage. By strategically ordering structure members, you can often reduce the footprint of your data objects, a critical consideration in resource‑constrained environments.

This article offers a concise yet comprehensive overview of structures in embedded C. We’ll cover their real‑world applications, how to declare them correctly, and the subtle rules of data alignment that affect the size of your structures.

Structures

When several variables of the same type share a logical relationship, an array is a convenient grouping. For instance, to hold the last 50 samples from an ADC that digitizes a voice input, you might use:

uint16_t voice[50];

Here, uint16_t is an unsigned 16‑bit integer defined in stdint.h, ensuring consistent size across platforms.

But what if you need to group variables of different types—say, an array of samples and the ADC’s sampling rate? Declaring them separately as independent variables creates unnecessary overhead. Instead, you can encapsulate them in a structure:

struct record {
    uint16_t voice[50];
    float    sample_rate;
};

The record structure now contains both an array of uint16_t and a float in a single, logically‑connected data object.

Why Are Structures Important?

Structures enable you to associate heterogeneous variables into a cohesive unit, simplifying manipulation and enhancing readability. They form the basis of more complex data structures, such as linked lists and message buffers, which are ubiquitous in embedded communication and sensor data handling.

For example, memory‑mapped peripherals on microcontrollers are often represented as structures that mirror the hardware register layout, allowing straightforward register access via member syntax.

Embedded C Structures: A Practical Guide to Definition, Usage, and Memory Optimization

Figure 1. Structures can be used to implement a linked list.

Embedded C Structures: A Practical Guide to Definition, Usage, and Memory Optimization

Figure 2. Memory map of an STM32 MCU. Image courtesy of Embedded Systems with ARM.

Declaring a Structure

First, you define a structure template. Consider this example:

struct record {
    uint16_t voice[4];
    float    sample_rate;
};

The template itself does not consume memory; allocation occurs only when you declare a variable of that type:

struct record mic1;

Now, mic1 occupies enough space for four uint16_t elements and one float. Access members via the dot operator:

mic1.voice[0] = 100;
float fs = mic1.sample_rate;

Other Ways to Declare a Structure

While the most common pattern defines the structure first and then declares variables, C offers alternative syntaxes:

Syntax 1: Tag and variable together

struct record {
    uint16_t voice[4];
    float    sample_rate;
} mic1;

Subsequent variables can be declared separately:

struct record mic2;

Syntax 2: Anonymous template

struct {
    uint16_t voice[4];
    float    sample_rate;
} mic1;

Here you cannot reuse the template elsewhere because it lacks a name.

Syntax 3: Anonymous nested structure

struct test {
    struct {
        float f;
        char  a;
    };
} test_var;

Access the inner members directly:

test_var.f = 1.2f;

Anonymous structures reduce verbosity but should be used judiciously for clarity.

Memory Layout for a Structure

The C standard guarantees that members are laid out in memory sequentially, in the order declared. For example:

struct Test2 {
    uint8_t  c;
    uint32_t d;
    uint8_t  e;
    uint16_t f;
} MyStruct;

On a 32‑bit machine, sizeof(MyStruct) is 12 bytes due to padding that aligns uint32_t to a 4‑byte boundary. Reordering members can eliminate padding:

struct Test2 {
    uint32_t d;
    uint16_t f;
    uint8_t  c;
    uint8_t  e;
} MyStruct;

Now sizeof(MyStruct) drops to 8 bytes—valuable savings in memory‑constrained firmware.

Embedded C Structures: A Practical Guide to Definition, Usage, and Memory Optimization

Figure 3. Data alignment can add padding to a structure’s memory layout.

Summary

Explore more of our embedded C tutorials here.

Embedded

  1. What Are Refractory Metals? An Expert Overview of Their Properties and Applications
  2. What Are Bi‑Fold Hinges? Features, Benefits, and Applications
  3. Deck Screws Explained: Types, Benefits, and How They Compare to Wood Screws
  4. What Are Split Washers? A Deep Dive Into Vibrational Locking Fasteners
  5. Mastering Digital Filtering on Embedded Microcontrollers: PowerQuad’s Dual Biquad IIR Engine in the LPC55S69
  6. Embedded C Unions Explained: Efficient Memory Sharing & Messaging
  7. Industrial Internet of Things (IIoT): Definition, Scope, and Industrial Impact
  8. Maintenance Data Explained: The Key to Reliable Asset Management
  9. Understanding Cloud Security: Key Benefits & Best Practices
  10. Mastering Modern Woodworking: Trends, Tech, and Techniques