🚀 Alguni Start learning

Unit 10: Structs

Making your own kind of thing.

Unit 10 of 11 in C programming for kids. Its 6 lessons are Keeping Things Together, Structs Get Copied, Lots of Them, Names for Types, Unions and Struct Master — below is everything each one explains, and a question or two from it to try.

Every sample on this page was compiled and run with gcc before it shipped, and prints exactly what it says it prints.

This unit opens with a fortnight’s trial of everything — no card needed — or with a family plan, bought in the iPhone app. The first two units of every track are free for ever. Try it in the app.

📦 Keeping Things Together

One box holding several values

A struct puts related values into a single thing. Describe the shape once, then make as many as you like — and reach inside with a dot.

C

#include <stdio.h>

struct Point {
    int x;
    int y;
};

int main() {
    struct Point p;
    p.x = 3;
    p.y = 4;
    printf("%d %d\n", p.x, p.y);
    return 0;
}

It prints

3 4

Filling it in as you make it

Braces set the members in the order they were declared. Anything you leave out starts at zero.

C

#include <stdio.h>

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

int main() {
    struct Point a = {1, 2, 3};
    struct Point b = {7};
    printf("%d %d %d\n", a.x, a.y, a.z);
    printf("%d %d %d\n", b.x, b.y, b.z);
    return 0;
}

It prints

1 2 3
7 0 0

Members can be any type at all

Including arrays — which is how a struct holds a name.

C

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

struct Dog {
    char name[10];
    int age;
};

int main() {
    struct Dog rex;
    strcpy(rex.name, "Rex");
    rex.age = 4;
    printf("%s is %d\n", rex.name, rex.age);
    return 0;
}

It prints

Rex is 4

Try it yourself

Why does the struct definition end with a semicolon?

  • A mistake in C
  • Because it is a declaration, and you could name a variable before the semicolon
  • To separate it from main
  • It does not need one

What does this print?

C

#include <stdio.h>

struct Box {
    int width;
    int height;
};

int main() {
    struct Box b = {3, 5};
    printf("%d\n", b.width * b.height);
    return 0;
}

Answer them in the app

📋 Structs Get Copied

Assigning one makes a real copy

This is the thing arrays would not do. b = a copies every member, and the two are then completely separate.

C

#include <stdio.h>

struct Point { int x; int y; };

int main() {
    struct Point a = {1, 2};
    struct Point b = a;
    b.x = 9;
    printf("%d %d\n", a.x, b.x);
    return 0;
}

It prints

1 9

And a function gets a copy too

Pass a struct and the function works on its own copy, so the original is safe. Compare that with an array, where the function shares the real thing.

C

#include <stdio.h>

struct Point { int x; };

void change(struct Point p) {
    p.x = 999;
}

int main() {
    struct Point a = {1};
    change(a);
    printf("%d\n", a.x);
    return 0;
}

It prints

1

Send its address to change the real one

A pointer to a struct uses -> instead of . — the arrow means "follow the pointer, then take that member".

C

#include <stdio.h>

struct Point { int x; };

void change(struct Point *p) {
    p->x = 999;
}

int main() {
    struct Point a = {1};
    change(&a);
    printf("%d\n", a.x);
    return 0;
}

It prints

999

A function can hand a whole struct back

Returning a struct copies it out to the caller, so it is safe to build one inside a function and return it.

C

#include <stdio.h>

struct Point { int x; int y; };

struct Point make(int x, int y) {
    struct Point p;
    p.x = x;
    p.y = y;
    return p;
}

int main() {
    struct Point p = make(3, 4);
    printf("%d %d\n", p.x, p.y);
    return 0;
}

It prints

3 4

Try it yourself

When do you use -> rather than .?

  • Whenever you like
  • When what you have is a pointer to the struct rather than the struct itself
  • Only inside functions
  • Only for ints

Answer it in the app

🗃️ Lots of Them

An array of structs

Structs go in arrays like anything else. Each set of inner braces fills one of them.

C

#include <stdio.h>

struct Score { int player; int points; };

int main() {
    struct Score board[3] = {{1, 10}, {2, 7}, {3, 4}};
    for (int i = 0; i < 3; i++) {
        printf("player %d: %d\n", board[i].player, board[i].points);
    }
    return 0;
}

It prints

player 1: 10
player 2: 7
player 3: 4

Structs inside structs

A member can be another struct, and the dots simply stack up.

C

#include <stdio.h>

struct Point { int x; int y; };
struct Rect { struct Point corner; int width; };

int main() {
    struct Rect r = {{2, 3}, 10};
    printf("%d %d %d\n", r.corner.x, r.corner.y, r.width);
    return 0;
}

It prints

2 3 10

A struct is as big as its parts, plus padding

C leaves gaps so each member starts at a tidy address. That is why this struct is 8 bytes and not 5 — an int likes to begin at a multiple of 4.

C

#include <stdio.h>

struct Padded { char c; int i; };
struct Plain { int a; int b; };
struct Tiny { char x; char y; };

int main() {
    printf("%d\n", (int)sizeof(struct Padded));
    printf("%d\n", (int)sizeof(struct Plain));
    printf("%d\n", (int)sizeof(struct Tiny));
    return 0;
}

It prints

8
8
2

Try it yourself

What does this print?

C

#include <stdio.h>

struct Pet { int legs; };

int main() {
    struct Pet pets[3] = {{4}, {2}, {8}};
    int total = 0;
    for (int i = 0; i < 3; i++) {
        total = total + pets[i].legs;
    }
    printf("%d\n", total);
    return 0;
}

Answer it in the app

🏷️ Names for Types

typedef saves you writing struct every time

typedef gives a type a shorter name. With it, struct Point p; becomes just Point p;.

C

#include <stdio.h>

typedef struct {
    int x;
    int y;
} Point;

int main() {
    Point p = {3, 4};
    printf("%d %d\n", p.x, p.y);
    return 0;
}

It prints

3 4

It works on any type

Not just structs. A good alias explains what a number is *for*.

C

#include <stdio.h>

typedef int Score;

int main() {
    Score points = 42;
    printf("%d\n", points);
    return 0;
}

It prints

42

enum gives names to numbers

An enum is a list of named whole numbers. They count up from 0 unless you say otherwise — and a name explains far more than a bare 2 ever will.

C

#include <stdio.h>

enum Colour { RED, GREEN, BLUE };

int main() {
    enum Colour c = GREEN;
    printf("%d %d %d\n", RED, GREEN, BLUE);
    printf("%d\n", c);
    return 0;
}

It prints

0 1 2
1

You can choose the numbers

Give one a value and the rest carry on from there.

C

#include <stdio.h>

enum Level { LOW = 5, MEDIUM, HIGH = 10 };

int main() {
    printf("%d %d %d\n", LOW, MEDIUM, HIGH);
    return 0;
}

It prints

5 6 10

Try it yourself

Why use an enum instead of just writing 0, 1 and 2?

  • It is faster
  • The names say what the numbers mean, so the code explains itself
  • It uses less memory
  • C requires it

Answer it in the app

🔀 Unions

One space, several names

A union looks like a struct but every member sits in the *same* space. It holds one of them at a time, so it is only as big as its widest member.

C

#include <stdio.h>

union Either {
    int number;
    char letter;
};

int main() {
    union Either e;
    e.number = 65;
    printf("%d\n", e.number);
    printf("%d\n", (int)sizeof(union Either));
    return 0;
}

It prints

65
4

Writing one forgets the other

They share the space, so setting the letter overwrites what the number was. A union only ever holds the thing you last put in.

C

#include <stdio.h>

union Either { int number; char letter; };

int main() {
    union Either e;
    e.number = 1000;
    e.letter = 66;
    printf("%d\n", e.letter);
    return 0;
}

It prints

66

Try it yourself

What is the difference between a struct and a union?

  • None, they are the same
  • A struct holds all its members at once; a union holds one at a time in the same space
  • A union is faster
  • A union can only hold numbers

What does this print?

C

#include <stdio.h>

struct Both { int a; int b; };
union One { int a; int b; };

int main() {
    printf("%d %d\n", (int)sizeof(struct Both), (int)sizeof(union One));
    return 0;
}

Answer them in the app

🏆 Struct Master

Try it yourself

What does this print?

C

#include <stdio.h>

struct P { int x; int y; };

int main() {
    struct P a = {1, 2};
    struct P b = a;
    a.x = 100;
    printf("%d %d\n", a.x, b.x);
    return 0;
}

Answer it in the app