SyntaxStudy
Sign Up
C Nested Structs and Arrays of Structs
C Beginner 1 min read

Nested Structs and Arrays of Structs

Structs can be nested — a struct member can itself be of struct type. This is useful for composing complex data types from simpler ones. A `Rectangle` might contain two `Point` members representing its corners. A `Transform` might contain separate `Position`, `Rotation`, and `Scale` structs. Accessing nested members chains the dot (or arrow) operator: `rect.topLeft.x`. Arrays of structs are the natural way to represent collections of records, such as a list of employees, a set of game entities, or a database table. You declare them like any array: `Employee staff[100]`. Combined with dynamic allocation, you can build resizable arrays of structs using `malloc` and `realloc`. Initialising an array of structs with a compound literal or a designated initialiser keeps code readable. Struct padding is an important consideration for performance and binary compatibility. The compiler inserts padding bytes between members to satisfy alignment requirements — for example, a `double` must typically be at an 8-byte-aligned address. This means a struct's size is not simply the sum of its members' sizes. You can see the actual size with `sizeof`, and rearranging members from largest to smallest type often minimises wasted padding.
Example
#include <stdio.h>
#include <string.h>

typedef struct {
    double x, y;
} Point;

typedef struct {
    Point  top_left;
    Point  bottom_right;
    char   label[32];
} Rectangle;

typedef struct {
    char   name[32];
    int    score;
    double time_sec;
} Player;

void print_rect(const Rectangle *r)
{
    printf("Rect '%s': (%.1f,%.1f)-(%.1f,%.1f)\n",
           r->label,
           r->top_left.x,     r->top_left.y,
           r->bottom_right.x, r->bottom_right.y);
}

int main(void)
{
    /* Nested struct initialisation */
    Rectangle r = {
        .top_left     = {0.0, 10.0},
        .bottom_right = {20.0, 0.0},
        .label        = "viewport"
    };
    print_rect(&r);

    /* Accessing nested members */
    double width  = r.bottom_right.x - r.top_left.x;
    double height = r.top_left.y - r.bottom_right.y;
    printf("Size: %.1f x %.1f\n", width, height);

    /* Array of structs */
    Player leaderboard[] = {
        {"Alice", 9500, 123.4},
        {"Bob",   8700, 145.2},
        {"Carol", 9900,  98.6}
    };
    int n = sizeof(leaderboard) / sizeof(leaderboard[0]);

    printf("\nLeaderboard:\n");
    for (int i = 0; i < n; i++)
        printf("  %s: %d pts  %.1fs\n",
               leaderboard[i].name,
               leaderboard[i].score,
               leaderboard[i].time_sec);

    /* Struct padding demo */
    printf("\nsizeof(Point)     = %zu\n", sizeof(Point));
    printf("sizeof(Rectangle) = %zu\n",  sizeof(Rectangle));
    printf("sizeof(Player)    = %zu\n",  sizeof(Player));

    return 0;
}