Chapter 14: Structures, Unions, and Bit-fields
Structures allow you to group multiple variables of different types under a single name. They are the primary way to define custom data types and objects in C.
I. Structures (struct)
A struct defines a block of memory where members are stored in the order they are declared.
struct Player {
int id;
char name[20];
float health;
};
struct Player p1 = {1, "Mario", 100.0f};
Accessing Members
- Dot Operator (
.): Used for struct variables.p1.id = 2; - Arrow Operator (
->): Used for pointers to structs.ptr->id = 3;(Shortcut for(*ptr).id).
II. Memory Padding and Alignment
The CPU is more efficient when reading data aligned to specific boundaries (e.g., 4 bytes for an int). To achieve this, the compiler inserts "invisible" bytes called padding between struct members.
struct PaddingExample {
char c; // 1 byte
// 3 bytes padding here
int i; // 4 bytes
} p;
printf("%zu\n", sizeof(p)); // Prints 8, not 5!
- Optimization: To minimize padding, always declare your struct members from largest type to smallest type.
III. Unions (union)
A union is like a struct, but all members share the exact same memory location. The size of a union is the size of its largest member.
- Use Case: Storing data that can be one of several types (e.g., a hardware packet that could be an
intor afloat).
union Data {
int i;
float f;
char str[20];
};
union Data data;
data.i = 10;
data.f = 22.5; // This overwrites the memory where i was!
IV. Bit-fields
Bit-fields allow you to specify the exact number of bits each member should occupy. This is essential for hardware drivers and network protocols.
struct Flags {
unsigned int is_active : 1; // 1 bit (0 or 1)
unsigned int priority : 3; // 3 bits (0 to 7)
unsigned int mode : 4; // 4 bits (0 to 15)
};
V. typedef
Use typedef to create aliases for your custom types, making the code more readable and easier to maintain.
typedef struct Player {
int id;
} Player;
Player p1; // No need to use 'struct Player' every time
VI. Anonymous Structs and Unions
Modern C (C11) allows you to nest structs and unions without giving them a name, allowing for cleaner code when accessing nested data.