C Structs Explained: From Basics to Embedded Bit-Fields
In C, a struct (structure) is a user-defined composite data type that groups variables of different types under a single name.
Structs are foundational in embedded systems, operating systems, and driver development, where they are commonly used to model hardware registers, protocol packets, and complex state objects.
🧱 Defining Struct Variables #
There are several valid ways to define and instantiate a structure in C.
Define and Instantiate Together #
struct string
{
char name[8];
int age;
char sex[2];
char depart[20];
float wage1, wage2, wage3, wage4, wage5;
} person; // Defines the struct and creates variable 'person'
This approach is concise and commonly used when the struct type is only needed once.
Define First, Instantiate Later #
struct string {
char name[8];
int age;
char sex[2];
char depart[20];
};
struct string person; // Create variable using the struct template
This is preferred when the structure type will be reused across multiple variables or translation units.
Anonymous Structs #
Anonymous structs omit the structure name and are useful for one-off use cases:
struct {
int id;
char name[16];
} Liming, Liuqi;
These are typically used for local data grouping inside functions.
🔍 Accessing and Assigning Members #
Struct members are accessed using the dot operator (.).
#include <stdio.h>
int main(void) {
struct {
char *name;
int age;
char group;
} stu1;
stu1.name = "Tom";
stu1.age = 18;
stu1.group = 'A';
printf("%s is %d years old in group %c\n",
stu1.name, stu1.age, stu1.group);
return 0;
}
The dot operator works only with actual struct variables, not pointers.
📚 Struct Arrays #
Struct arrays are ideal for managing collections of related objects, such as students, devices, or packets.
struct {
char name[8];
char sex[2];
int age;
char addr[40];
} student[40]; // Array of 40 student structures
student[0].age = 18;
Each element in the array is a fully independent struct.
👉 Struct Pointers #
For large structures or dynamically allocated memory, pointers to structs are preferred.
#include <stdlib.h>
#include <string.h>
struct string {
char name[8];
int age;
};
struct string *student;
student = (struct string *)malloc(sizeof(struct string));
strcpy(student->name, "Jack");
student->age = 18;
When accessing members through a pointer, use the arrow operator (->).
student->ageis shorthand for(*student).age
🧩 Bit-Fields (位结构) #
Bit-fields allow precise control over individual bits within a struct. This is extremely common in embedded programming when mapping C structures directly to hardware registers.
struct {
unsigned incon : 8; /* bits 0–7 */
unsigned txcolor : 4; /* bits 8–11 */
unsigned bgcolor : 3; /* bits 12–14 */
unsigned blink : 1; /* bit 15 */
} ch;
Why Bit-Fields Matter #
- Efficient memory usage
- Clear mapping to register layouts
- Improved readability vs manual bit masking
⚠️ Note: Bit-field layout and alignment can be compiler- and endian-dependent. Always verify with the target compiler and hardware.
🧾 Using typedef with Structs
#
Using typedef simplifies syntax and improves readability—especially in large codebases.
typedef struct person {
int age;
char *name;
} student;
student stu1; // No need to write 'struct person'
This pattern is widely used in:
- Kernel code
- Device drivers
- Embedded firmware APIs
🎯 Key Takeaways #
structgroups heterogeneous data into a single logical unit- Use arrays and pointers for scalability and performance
- Bit-fields are essential for hardware-level programming
typedef structdramatically improves code clarity
A solid understanding of C structs is non-negotiable for anyone working close to the hardware or performance-critical systems.