Ai Ho

Jet Station πŸš€

Menu

🏠 Home | πŸš€ Embedded Systems | 🧰 Development Toolbox | πŸŽ“ Training Courses | πŸ“š Documents

Struct and Union Data Types

🎯 In embedded C programming, struct and union are essential user-defined data types that enable efficient management of related data. A struct (structure) allows grouping variables of different types under a single name, making it easier to organize and access complex data, such as sensor readings or device configurations. Each member of a struct occupies its own memory space, enabling simultaneous storage of multiple values.

Struct and Union Data Types

πŸ’‘ A union, on the other hand, provides a way to store different data types in the same memory location. All members of a union share the same memory, so only one value can be stored at a time. This is particularly useful in memory-constrained embedded systems where optimizing resource usage is critical.

πŸ’‘ Both struct and union play a vital role in embedded applications, offering flexibility, improved code readability, and efficient memory management for handling diverse data requirements.

Table of Contents

Struct Data Type

Key Points

πŸ”‘ Here are the key points of the struct data type in C:

Use Cases

Here’s a typical use case for using the struct data type in embedded systems:

πŸ“Œ Structs are commonly used to group related data for hardware peripherals, such as sensors or communication modules. For example, you can define a struct to store all relevant information about a sensor, including its ID, measurement value, status, and configuration settings. This approach simplifies data management, improves code readability, and makes it easier to pass complex data between functions or modules in embedded applications.

Declaration

Initialization

Union Data Type

Key Points

πŸ”‘ Here are the key points of the union data type in C:

πŸ“Œ Unions are commonly used when a variable may need to store different types of data at different times, such as protocol packets, hardware registers, or interpreting raw data from peripherals. For example, a union can be used to access the same memory as an integer or a byte array, depending on the application’s requirements. This approach helps save memory and simplifies data handling in embedded applications.

Declaration

Initialization

Modification

Demo Project

πŸš€ Source code: demo project

How to calculate the size of struct and union data types?

πŸ‘‰ The size of a struct is typically the sum of the sizes of all its members, plus any padding added for alignment. For a union, its size is determined by its largest member, since all members share the same memory space.

// Example: struct data type for a rectangle shape
typedef struct {
	uint16_t width_u16;
	uint16_t height_u16;
	uint32_t area_u32;
} Rectangle_st;
// Example: union data type for register access
typedef struct {
	uint32_t bit0 : 1;
	uint32_t bit1 : 1;
	uint32_t bit2 : 1;
	uint32_t bit3 : 1;
	uint32_t reserved : 28;
} RegisterBits_st; // Access individual bits

typedef union {
	uint32_t register_u32;        // Access the entire register
	RegisterBits_st bits_st;      // Access individual bits
	uint8_t registerBytes_u8[4];  // Access as bytes
	uint16_t registerHalfWords_u16[2]; // Access as half-words
} RegisterType_un;

[!TIP] Using typedef before struct and union lets you create a type alias for the structure or union. This makes your code cleaner and easier to read, as you can use the alias directly without repeatedly writing struct or union before variable declarations. For example, with typedef struct { ... } RegisterBits_st;, you can declare variables as RegisterBits_st reg; instead of struct RegisterBits_st reg;. This is especially useful in embedded systems where code clarity and brevity are important.

πŸ‘‰ Actual size of struct and union data types in embedded system memory: Data Size in Embedded System

Initialize the struct variable

πŸ‘‰ You can initialize a struct variable when you declare it, assigning values to its members immediately. Struct Initialization

Modify struct members

πŸ‘‰ After a struct variable has been declared, you can update its members at any time using the dot operator. Struct Member Update

Modify union members

πŸ‘‰ You can modify any member of a union variable after it has been declared. However, updating one member will immediately affect the values of all other members, since they share the same memory space.

Padding bytes for aligment

[!IMPORTANT] The order of struct members can impact the overall size of a struct because of memory alignment and padding. Grouping members of similar or decreasing size together helps minimize padding and improves memory efficiency.

[!IMPORTANT] The amount of padding bytes inserted depends on the microcontroller’s architecture and its memory alignment requirements.

πŸ‘‡ The following demonstration shows how padding bytes are used for alignment in the 32-bit STM32F103C6 microcontroller and offers tips for optimizing memory usage.

Padding bytes in microcontroller memory layout

πŸ‘‰ Padding bytes may be inserted if struct members are not arranged efficiently. For example, 2 bytes of padding can be added after a uint16_t member to align the next member on a 32-bit boundary. The uint32_t member naturally fits the 32-bit memory layout without requiring extra padding.

typedef struct {
	uint16_t width_u16;
	uint32_t area_u32;
	uint16_t height_u16;
} Rectangle_st;

The padding bytes are visible in the microcontroller’s memory layout: Padding Bytes in Memory Layout

How to remove padding bytes to save memory?

[!TIP] One effective way to reduce padding bytes is to arrange struct members from largest to smallest, or to group them according to the bit-width supported by the microcontroller.

typedef struct {
	uint16_t width_u16;
	uint16_t height_u16;
	uint32_t area_u32;
} Rectangle_st;

[!TIP] Another method is to use compiler-specific features, such as the packed attribute in the ARM compiler, to force members to be allocated consecutively without padding. Similar options are available in other compilers.

typedef struct __attribute__((packed)) {
	uint16_t width_u16;
	uint32_t area_u32;
	uint16_t height_u16;
} Rectangle_st;

πŸš€ You can use this demo project to experiment further and deepen your understanding of struct and union data types.

Explore More Topics

|πŸ‘ˆ Previous | Next πŸ‘‰|

Repositories

πŸš€ My Repositories

Contact & Discussion

If you have any thing would like to discuss or cooperate with me, please don’t hesitate to contact me via:

Home Page

🏠 Home