LearnFrenzy
Sign in Take a free test

Structures, Unions and Enums · Lesson 29 of 35

Arrays of Structures and Pointers to Structures

5 min read Updated Nov 7, 2026 Saurabh Samir

Real programs work with many records: all the students in a class, all the products in a shop. An array of structures stores them, and pointers to structures let functions read and update records efficiently. The "student record" or "employee database" program built here is a standard lab and mini-project exercise.

In this lesson

  • Arrays of structures
  • Pointers to structures and the arrow operator
  • Passing structs to functions by value vs by pointer
  • Searching and sorting records with qsort

An array of structures

#include <stdio.h>

typedef struct {
    int roll;
    char name[20];
    int marks[3];
} Student;

int main(void) {
    Student cls[] = {
        {1, "Asha",  {78, 85, 92}},
        {2, "Ravi",  {65, 70, 58}},
        {3, "Meera", {90, 88, 95}},
    };
    int n = sizeof cls / sizeof cls[0];

    int top = 0, best_total = -1;
    for (int i = 0; i < n; i++) {
        int total = cls[i].marks[0] + cls[i].marks[1] + cls[i].marks[2];
        printf("%d %-6s total %3d  average %.1f\n", cls[i].roll, cls[i].name, total, total / 3.0);
        if (total > best_total) { best_total = total; top = i; }
    }
    printf("Topper: %s with %d\n", cls[top].name, best_total);
    return 0;
}

Output

1 Asha   total 255  average 85.0
2 Ravi   total 193  average 64.3
3 Meera  total 273  average 91.0
Topper: Meera with 273

Pointers to structures and the arrow operator

#include <stdio.h>

typedef struct {
    char name[20];
    double balance;
} Account;

int main(void) {
    Account acc = {"Asha", 5000.0};
    Account *p = &acc;

    printf("%s has %.2f\n", (*p).name, (*p).balance);   // dereference, then dot
    p->balance += 1500;                                 // arrow: the same, shorter
    printf("%s has %.2f\n", p->name, p->balance);
    return 0;
}

Output

Asha has 5000.00
Asha has 6500.00

p->member means (*p).member. The brackets in the long form are required, because . binds tighter than *.

Passing structures to functions

#include <stdio.h>
#include <stdbool.h>

typedef struct {
    char name[20];
    double balance;
} Account;

void print_account(const Account *a) {          // read-only: const pointer, no copy
    printf("%-6s %10.2f\n", a->name, a->balance);
}

bool withdraw(Account *a, double amount) {      // modifies the caller's struct
    if (amount <= 0 || amount > a->balance) return false;
    a->balance -= amount;
    return true;
}

Account with_interest(Account a, double rate) { // by value: works on a copy, returns a new struct
    a.balance *= 1 + rate / 100;
    return a;
}

int main(void) {
    Account acc = {"Ravi", 2000.0};
    print_account(&acc);
    printf("withdraw 500: %s\n", withdraw(&acc, 500) ? "ok" : "refused");
    printf("withdraw 9000: %s\n", withdraw(&acc, 9000) ? "ok" : "refused");
    Account next_year = with_interest(acc, 7.5);
    print_account(&acc);
    print_account(&next_year);
    return 0;
}

Output

Ravi      2000.00
withdraw 500: ok
withdraw 9000: refused
Ravi      1500.00
Ravi      1612.50
Pass byCopies the struct?Can modify the original?Use for
value: f(Account a)yesnosmall structs, returning a modified copy
pointer: f(Account *a)noyesupdates; large structs
const pointer: f(const Account *a)nonoread-only access to large structs

Sorting and searching records

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int id;
    char name[20];
    double salary;
} Employee;

int by_salary_desc(const void *a, const void *b) {
    const Employee *x = a, *y = b;
    return (y->salary > x->salary) - (y->salary < x->salary);
}

int by_name(const void *a, const void *b) {
    return strcmp(((const Employee *)a)->name, ((const Employee *)b)->name);
}

Employee *find_by_id(Employee *list, int n, int id) {
    for (int i = 0; i < n; i++) if (list[i].id == id) return &list[i];
    return NULL;
}

int main(void) {
    Employee staff[] = {{11, "Kiran", 72000}, {12, "Asha", 95000}, {13, "Ravi", 61000}, {14, "Dev", 88000}};
    int n = sizeof staff / sizeof staff[0];

    qsort(staff, n, sizeof staff[0], by_salary_desc);
    printf("By salary:\n");
    for (int i = 0; i < n; i++) printf("  %-6s %.0f\n", staff[i].name, staff[i].salary);

    qsort(staff, n, sizeof staff[0], by_name);
    printf("By name:");
    for (int i = 0; i < n; i++) printf(" %s", staff[i].name);
    printf("\n");

    Employee *e = find_by_id(staff, n, 13);
    if (e != NULL) {
        e->salary *= 1.10;                       // raise via the pointer
        printf("%s now earns %.0f\n", e->name, e->salary);
    }
    return 0;
}

Output

By salary:
  Asha   95000
  Dev    88000
  Kiran  72000
  Ravi   61000
By name: Asha Dev Kiran Ravi
Ravi now earns 67100

Practice

Try it yourself

  1. Write void apply_discount(Product *p, int percent) and use it on every product in an array.

    Show solution
    #include <stdio.h>
    
    typedef struct { char name[20]; double price; } Product;
    
    void apply_discount(Product *p, int percent) {
        p->price -= p->price * percent / 100.0;
    }
    
    int main(void) {
        Product items[] = {{"Mouse", 600}, {"Keyboard", 2500}};
        for (int i = 0; i < 2; i++) {
            apply_discount(&items[i], 10);
            printf("%s: %.2f\n", items[i].name, items[i].price);
        }
        return 0;
    }

    Output

    Mouse: 540.00
    Keyboard: 2250.00

Quick check

What does p->x mean?

(*p).x – member x of the struct p points to.

Why pass large structs by pointer?

To avoid copying them and (without const) to let the function modify the original.

How do you sort an array of structs by a member?

qsort with a comparator that casts its void pointers to the struct type and compares that member.

Summary

  • Arrays of structs hold records; index then dot: cls[i].name.
  • Use the arrow operator with pointers; pass by const pointer to read, by pointer to modify.
  • qsort with a struct comparator sorts records by any member.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Search LearnFrenzy

Esc

Quick links