Struct pointers Ready
A struct, and a pointer to it.
main.c

                

Ready

Statements run 0 Lines printed 0
Ready

Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode

How it works

The ideas behind the lab

Exactly what you watched happen, in plain steps.

Pointers to structs and the arrow

A pointer can hold the address of a whole struct. To reach a member through it you follow the pointer and then pick the member: (*p).x — which C lets you write as p->x. Functions usually receive structs this way: passing a pointer copies only 8 bytes and lets the function change the caller's struct. typedef gives a struct type a short name, and a struct may contain a pointer to its own type, which links records together.

typedef struct Point { int x, y; } Point;   // Point = struct Point

Point a = {1, 2};
Point *p = &a;
p->x = 5;               // same as (*p).x = 5

void move(Point *p, int dx) { p->x += dx; }
move(&a, 3);            // a.x is now 8

typedef struct Node { int value; struct Node *next; } Node;
Point a; Point *p = &a;
Expression Meaning Use it when
a.x member x of the struct a you have the struct itself
p->x member x of the struct p points to you have a pointer
(*p).x the same as p->x rarely — the arrow is shorter
f(a) passes a copy of the whole struct small structs that must not change
f(&a) passes the address (8 bytes) the function changes it, or it is big
const Point *p a pointer the function may only read through large read-only arguments

The arrow operator

  1. p->member is short for (*p).member.
  2. The brackets in (*p).x matter: *p.x would mean *(p.x).
  3. Use . with a struct variable and -> with a pointer to a struct.
  4. Chains work too: list->next->value.
  5. A pointer to a struct must point to a real struct (or be NULL) before ->.

Structs and functions

  1. A struct argument is copied completely, like an int.
  2. Changes to that copy are lost when the function returns.
  3. Pass &s and take a pointer parameter to change the caller's struct.
  4. A function can also return a struct: Point add(Point a, Point b).
  5. For big structs, pass const T * even when only reading — it avoids the copy.

typedef and self-reference

  1. typedef existing_type NewName; creates an alias, e.g. typedef unsigned int uint;
  2. typedef struct { … } Point; lets you write Point instead of struct Point.
  3. A struct cannot contain itself, but it can contain a pointer to its own type.
  4. Inside the struct use the tag: struct Node *next; (the typedef name is not known yet).
  5. Nodes linked by next pointers form a linked list; NULL marks the end.
Walkthrough

A linked list built with malloc

Every line, explained.

1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct Node {
5 int value;
6 struct Node *next; A pointer to the next node.
7 } Node;
8
9 Node *push(Node *head, int value) Adds a node in front.
10 {
11 Node *n = malloc(sizeof *n); A new node on the heap.
12 if (n == NULL) return head;
13 n->value = value;
14 n->next = head; It points to the old first node …
15 return n; … and becomes the new head.
16 }
17
18 void printList(const Node *p)
19 {
20 for (; p != NULL; p = p->next) Follow the links until NULL.
21 printf("%d -> ", p->value);
22 printf("NULL\n");
23 }
24
25 int main(void)
26 {
27 Node *head = NULL; An empty list.
28 head = push(head, 3);
29 head = push(head, 2);
30 head = push(head, 1);
31 printList(head); Prints 1 -> 2 -> 3 -> NULL
32 while (head != NULL) { Free every node.
33 Node *next = head->next; Save the link BEFORE freeing.
34 free(head);
35 head = next;
36 }
37 return 0;
38 }
Common mistakes

Spot the bug

Mistakes almost every beginner makes — and how to fix them.

Using . with a pointer

✗ Wrong
Point *p = &a;
p.x = 5;    // error
✓ Right
Point *p = &a;
p->x = 5;

p is an address, not a struct. Use -> (or (*p).x).

*p.x instead of (*p).x

✗ Wrong
*p.x = 5;
✓ Right
(*p).x = 5;   // or p->x = 5;

. binds tighter than *, so *p.x means *(p.x).

Passing a struct by value to change it

✗ Wrong
void reset(Point p) { p.x = 0; }
reset(a);   // a unchanged
✓ Right
void reset(Point *p) { p->x = 0; }
reset(&a);

The function changes only its copy. Pass a pointer.

Using the typedef name inside its own struct

✗ Wrong
typedef struct Node {
    int v;
    Node *next;   // error: Node not yet known
} Node;
✓ Right
typedef struct Node {
    int v;
    struct Node *next;
} Node;

The name Node only exists after the typedef ends; inside, use struct Node.

Freeing a node before reading its next

✗ Wrong
free(head);
head = head->next;   // use after free
✓ Right
Node *next = head->next;
free(head);
head = next;

After free the node may already be overwritten.

Practice

Check your understanding

Answer each question — you will see the explanation straight away.

0 / 5 correct
Question 1

Point a = {1, 2}; Point *p = &a; p->y = 7; — what is a.y?

Question 2

Which expression is the same as p->x?

Question 3

void f(Point p) { p.x = 0; } — Point a = {5, 5}; f(a); What is a.x?

Question 4

What does typedef struct { int x, y; } Point; let you write?

Question 5

In a linked list, what does the last node's next usually hold?

Assessment

Structures, Pointers & Functions quiz

Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.