Skip to content
Laviyx Learn

Try

C course menu

Structures in C: struct, typedef, Arrays of Structs and Pointers to Structs

Learn structures in C: defining a struct, initialising members with designated initialisers, typedef, copying and passing structs to functions, the arrow operator for pointers to structs, arrays of structs, nested structs, and padding and sizeof.

Intermediate10 min readUpdated
On this page

A structure (struct) groups related values of different types under one name, such as a student's roll number, name and marks. It is C's way of building your own data types.

Defining and using a struct#

C
#include <stdio.h>

struct Student {
    int roll;
    char name[32];
    double cgpa;
};

int main(void) {
    struct Student s = {101, "Asha", 8.7};
    printf("%d %s %.1f\n", s.roll, s.name, s.cgpa);

    s.cgpa = 9.1;                         /* the dot operator reaches a member */
    printf("updated: %.1f\n", s.cgpa);
    return 0;
}
Output
101 Asha 8.7
updated: 9.1

Designated initialisers#

C99 lets you name the members you initialise. The order no longer matters, and any member you leave out is set to zero:

C
struct Point { int x, y, z; };

struct Point p = { .y = 5, .x = 2 };
printf("%d %d %d\n", p.x, p.y, p.z);
Output
2 5 0

typedef#

typedef gives a type a shorter name, so you can write Student instead of struct Student:

C
#include <stdio.h>

typedef struct {
    char code[8];
    int credits;
} Course;

int main(void) {
    Course c = { .code = "CS101", .credits = 4 };
    printf("%s: %d credits\n", c.code, c.credits);
    return 0;
}
Output
CS101: 4 credits

Copying and passing structs#

Unlike arrays, structs can be assigned with = and returned from functions. The whole struct is copied, including any arrays inside it:

C
#include <stdio.h>

typedef struct { double x, y; } Vec2;

Vec2 add(Vec2 a, Vec2 b) {
    Vec2 r = { a.x + b.x, a.y + b.y };
    return r;
}

int main(void) {
    Vec2 a = {1.5, 2.0}, b = {0.5, 3.0};
    Vec2 c = add(a, b);
    Vec2 copy = c;
    copy.x = 100;
    printf("c = (%.1f, %.1f), copy.x = %.1f\n", c.x, c.y, copy.x);
    return 0;
}
Output
c = (2.0, 5.0), copy.x = 100.0

Structs cannot be compared with ==; compare their members.

Pointers to structs and the arrow operator#

Passing a large struct by value copies all of it. Passing a pointer is cheaper and lets the function change the original. p->member is shorthand for (*p).member:

C
#include <stdio.h>

typedef struct {
    char holder[32];
    double balance;
} Account;

int withdraw(Account *acc, double amount) {
    if (amount <= 0 || amount > acc->balance) return 0;
    acc->balance -= amount;
    return 1;
}

void print_account(const Account *acc) {
    printf("%s: %.2f\n", acc->holder, acc->balance);
}

int main(void) {
    Account a = { "Ravi", 5000.0 };
    printf("%d\n", withdraw(&a, 1200));
    printf("%d\n", withdraw(&a, 9000));
    print_account(&a);
    return 0;
}
Output
1
0
Ravi: 3800.00

Use const Account * for functions that only read the struct.

Arrays of structs#

C
#include <stdio.h>

typedef struct {
    const char *name;
    int marks;
} Result;

int main(void) {
    Result results[] = {
        {"Asha", 87}, {"Ravi", 92}, {"Meena", 78}, {"Kiran", 92},
    };
    int n = sizeof results / sizeof results[0];

    int best = 0;
    for (int i = 1; i < n; i++) {
        if (results[i].marks > results[best].marks) best = i;
    }
    printf("top: %s (%d)\n", results[best].name, results[best].marks);
    return 0;
}
Output
top: Ravi (92)

Only the first student with the highest mark is reported, because the comparison uses >, not >=.

Nested structs#

C
typedef struct { int day, month, year; } Date;
typedef struct {
    char title[40];
    Date due;
} Task;

Task t = { "Submit project", { 15, 11, 2026 } };
printf("%s by %02d/%02d/%d\n", t.title, t.due.day, t.due.month, t.due.year);
Output
Submit project by 15/11/2026

Padding and sizeof#

The compiler may insert unused padding bytes between members so that each one is aligned in memory, so a struct can be larger than the sum of its members:

C
#include <stdio.h>

struct Loose { char a; int b; char c; };
struct Tight { int b; char a; char c; };

int main(void) {
    printf("%zu %zu\n", sizeof(struct Loose), sizeof(struct Tight));
    return 0;
}
Output
12 8

(These sizes come from a typical x86-64 compiler with a 4-byte int.) Ordering members from largest to smallest often reduces padding. Always use sizeof rather than adding up member sizes yourself.

Practice#

Practice exercise

Define typedef struct { char name[20]; int qty; double price; } Item;. Write double item_total(const Item *it) and use it on an array of three items to print each line and the order total.

Show solution
C
#include <stdio.h>

typedef struct {
    char name[20];
    int qty;
    double price;
} Item;

double item_total(const Item *it) {
    return it->qty * it->price;
}

int main(void) {
    Item cart[] = {
        {"Notebook", 3, 45.0},
        {"Pen", 10, 12.5},
        {"Bag", 1, 799.0},
    };
    double total = 0;
    for (int i = 0; i < 3; i++) {
        double line = item_total(&cart[i]);
        printf("%-10s %2d x %7.2f = %8.2f\n", cart[i].name, cart[i].qty, cart[i].price, line);
        total += line;
    }
    printf("Total: %.2f\n", total);
    return 0;
}
Output
Notebook    3 x   45.00 =   135.00
Pen        10 x   12.50 =   125.00
Bag         1 x  799.00 =   799.00
Total: 1059.00

Key takeaway#

Finished this lesson?