typedef
typedef gives an existing type a new name. It shortens long type names like struct point and function pointer types, documents what a type means (Celsius rather than double), and hides platform details behind one definition.
Basic typedef
#include <stdio.h> typedef double Celsius; typedef unsigned long long ByteCount; int main(void) { Celsius today = 21.5; ByteCount file_size = 4500000000ULL; printf("%.1f C, %llu bytes\n", today, file_size); return 0; }
21.5 C, 4500000000 bytes
A typedef doesn't create a new, separate type — Celsius is still a double, and the compiler will happily mix them. It's a name for readers, not a safety check.
typedef with structs
The most common use: avoid writing struct everywhere.
#include <stdio.h> typedef struct { double x; double y; } Vec2; Vec2 vec_add(Vec2 a, Vec2 b) { return (Vec2) { a.x + b.x, a.y + b.y }; } int main(void) { Vec2 position = { 1.0, 2.0 }; Vec2 velocity = { 0.5, -0.25 }; for (int t = 0; t < 3; t++) { position = vec_add(position, velocity); printf("(%.2f, %.2f)\n", position.x, position.y); } return 0; }
(1.50, 1.75) (2.00, 1.50) (2.50, 1.25)
For a struct that refers to itself (like a linked list node), give the struct a tag as well, because the typedef name doesn't exist yet inside the definition:
#include <stdio.h> typedef struct Node { int value; struct Node *next; // the tag is needed here } Node; int main(void) { Node third = { 3, NULL }, second = { 2, &third }, first = { 1, &second }; for (Node *n = &first; n != NULL; n = n->next) printf("%d ", n->value); printf("\n"); return 0; }
1 2 3
Function pointer types
Function pointer declarations are hard to read; a typedef fixes that (as lesson 39 showed):
#include <stdio.h> typedef int (*Comparator)(int, int); int ascending(int a, int b) { return a - b; } int descending(int a, int b) { return b - a; } void sort3(int v[3], Comparator cmp) { for (int i = 0; i < 2; i++) for (int j = 0; j < 2 - i; j++) if (cmp(v[j], v[j + 1]) > 0) { int t = v[j]; v[j] = v[j + 1]; v[j + 1] = t; } } int main(void) { int v[3] = { 7, 2, 9 }; sort3(v, ascending); printf("%d %d %d\n", v[0], v[1], v[2]); sort3(v, descending); printf("%d %d %d\n", v[0], v[1], v[2]); return 0; }
2 7 9 9 7 2
(Subtracting is fine for these small numbers; for arbitrary ints, use the overflow-safe comparison from lesson 39.)
Typedefs in the standard library
You've already used several: size_t, ptrdiff_t, int32_t, uint8_t, FILE, time_t. Each one hides a platform-specific choice — size_t might be unsigned long on one system and unsigned long long on another — so code using the typedef works everywhere.
Style
Opinions differ. Many projects typedef structs to CamelCase names (Vec2, Node). Others, including the Linux kernel, prefer writing struct node explicitly so it's always obvious a type is a struct, and use typedef mainly for opaque types and function pointers. Avoid typedefs that hide a pointer, such as typedef Node *NodePtr; — they make it unclear when a value is a pointer, and const NodePtr doesn't mean what it looks like.
Names ending in _t are reserved by POSIX for its own types, so it's best not to invent your own _t names in programs for Unix-like systems.
Try it yourself
Define a Money type holding cents, and functions to add amounts and print them.
Rent 950.00 Internet 34.99 Groceries 412.75 Total 1397.74