Structures, Unions, and Bit-fields

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!

char c1 BytePadding (3B)int i4 Bytes

  • 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 int or a float).
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.