Nearby lessons
107 of 124C - typedef
typedef creates a new name for an existing type. Learn how it removes the struct keyword, tames pointer and function-pointer declarations, documents intent — and when it hides more than it helps.
The Basic Syntax
Write typedef, then the existing type, then the new name. It reads like a variable declaration with typedef bolted on the front — because that is exactly how the grammar works:
It Is an Alias, Not a New Type
typedef name and the original type are the same type with two spellings. The compiler will not stop you mixing them, and no new conversion rules appear. If you want genuine type safety, wrap the value in a one-member structure instead.The Main Use — Structures
C requires struct Student s;. A typedef lets you write Student s;, which is why almost every real codebase uses one:
Keep the Tag for Self-Reference
Inside its own braces the typedef name does not exist yet. A linked-list node needs the tag:
With Unions and Enums
The same trick removes the union and enum keywords:
Taming Function Pointers
This is where typedef earns its place. Compare the raw declaration with the aliased one:
The New Name Goes Where the Variable Would
For array and pointer types, the alias name sits in the middle — exactly where a variable name would sit in an ordinary declaration:
The Pointer-Typedef Trap
typedef that hides a pointer surprises everyone who reads it. With typedef int *IntPtr;, the declaration IntPtr a, b; makes both pointers — which is the opposite of int *a, b;. Worse, const IntPtr p means int *const p (a const pointer), not const int *p. Most style guides ban pointer typedefs for exactly this reason.Portable Fixed-Width Types
The standard library already ships the typedefs you most often want. Prefer <stdint.h> to rolling your own:
| Type | Meaning | Header |
|---|---|---|
int32_t, uint8_t | Exactly that many bits | <stdint.h> |
size_t | A size or count; never negative | <stddef.h> |
ptrdiff_t | The difference of two pointers | <stddef.h> |
FILE | A file stream | <stdio.h> |
time_t | A calendar time | <time.h> |
typedef vs #define
They look similar and behave very differently. #define is blind text substitution; typedef is understood by the compiler:
typedef | #define | |
|---|---|---|
| Handled by | The compiler | The preprocessor |
| Respects scope | Yes | No — from the line onward |
| Works for pointers | Correctly | Breaks on multiple declarators |
| Can alias arrays | Yes | No |
| Needs a semicolon | Yes | No |
Common Mistakes
- Reversing the order — it is
typedef int Metres;, nevertypedef Metres int;. - Expecting type safety — two typedefs of
intare freely interchangeable. - Forgetting the semicolon — a
typedefis a declaration and needs one. - Self-reference in an anonymous struct — keep the tag for linked structures.
- Hiding pointers —
const MyPtr palmost never means what the reader expects. - Aliasing an already-clear type —
typedef int Integer;adds a word to learn and no information.
typedef when it removes noise the reader does not need — struct keywords, function-pointer syntax, platform-specific widths. Avoid it when it removes information the reader does need, which is nearly always the case for pointers.- typedef existingType newName; — the new name comes last.
- It creates an alias, never a new type; no conversion rules change.
- typedef struct {...} Name; lets you drop the struct keyword.
- It makes function-pointer declarations readable.
- Hiding a pointer behind a typedef often causes more confusion than it saves.