5.1.26 · D5C Programming

Question bank — Typedef

1,440 words7 min readBack to topic

Before we start, three words we lean on constantly. A type is the label C attaches to data so it knows its size and what operations are legal (e.g. int, char *). A declarator is the part of a declaration that names a thing, possibly wrapped in *, [], or () — e.g. in int *p, the declarator is *p. A tag namespace is a separate list C keeps for the names written after struct/union/enum, kept apart from ordinary names.


True or false — justify

Every answer is "true/false because…" — the reasoning is the point.

typedef creates a brand-new data type distinct from the original.
False. It only creates an alias; the aliased name and the original are fully interchangeable, and the compiler treats them as the same type in every check.
typedef int Age; Age a = 5; int b = a; compiles with no cast.
True. Age is int, so assigning between them is assigning int to int — no conversion, no warning.
typedef is processed by the C preprocessor, like #define.
False. typedef is handled by the compiler during real parsing; #define is blind text substitution done earlier by the preprocessor.
With typedef int* IntPtr; IntPtr a, b; both a and b are pointers.
True. The * is baked into the alias itself, so each declared name inherits the full pointer type — unlike raw int* a, b;.
typedef struct Point Point; is illegal because the name Point is used twice.
False. The two Points live in different namespaces — the first is a struct tag, the second an ordinary type name — so they don't collide.
A typedef uses more memory at runtime than using the original type directly.
False. It's purely a compile-time name; zero runtime cost, zero extra bytes. The generated machine code is identical.
typedef unsigned long ULong; then changing it to typedef unsigned int ULong; updates every variable declared with ULong.
True. That single-point change is exactly the portability benefit — every use re-reads the new meaning at the next compile.
You can typedef a type to a name and then typedef that name again to a third name.
True. Aliases chain; typedef int A; typedef A B; makes B an alias for A which is an alias for int — all mean int.
typedef declarations obey C scope rules.
True. A typedef inside a function is local to that block, unlike #define which ignores scope entirely and leaks everywhere below it.

Spot the error

Each snippet has one conceptual flaw. Name it.

#define INTPTR int* then INTPTR a, b; — is b a pointer?
No — this is the classic trap. Text substitution gives int* a, b;, so only a is a pointer and b is a plain int. Use a typedef if you want both pointers.
typedef int; — what's wrong?
There is no new name — the declarator (the "variable name" slot) is missing, so there's nothing to alias. A typedef must supply a fresh identifier.
typedef struct { int x; } ; used later as Point p; — why does Point fail?
The anonymous struct was given no alias name, so Point was never defined. It should be typedef struct { int x; } Point;.
typedef int Meter; Meter m = 3; Meter += 1; — spot the mistake.
You can't do arithmetic on the type name Meter; you operate on the variable m. It should be m += 1;. See Pointers in C for the type-vs-value distinction.
typedef Node struct node; — why won't this compile?
The order is reversed. typedef reads like a variable declaration: existing type first, new name last — typedef struct node Node;.
typedef int (Operation)(int,int); intended as a function pointer — what's missing?
The *. As written, Operation aliases a function type, not a pointer to function. You need typedef int (*Operation)(int,int); — see Function Pointers.
#define uint unsigned int then uint * p; inside a struct — any hidden risk versus typedef?
#define ignores scope, so this macro replaces uint everywhere below in the file, even inside unrelated code; a typedef would stay confined to its declared scope.

Why questions

typedef reuses variable-declaration syntax rather than a clean alias X = Y; form. Why is that actually convenient?
Because the same declarator rules that build complex variable types (pointers, arrays, function pointers) then build complex type names for free — one grammar, no second syntax to learn.
Why does typedef struct Point Point; let you drop the struct keyword afterward?
The alias Point lives in the ordinary type namespace, so writing Point p; finds it directly, whereas the bare tag Point requires the struct prefix to reach the tag namespace.
Why is typedef preferred over #define for function-pointer types?
Function-pointer declarators are complex and position-sensitive; typedef parses them once as real syntax, while #define's dumb substitution breaks when the name must sit inside the declarator (e.g. int (*NAME)(int)).
Why does a pointer typedef "baking in" the * sometimes surprise people?
Readers expect * to bind to the variable in a declaration, but inside an alias it's already part of the type, so IntPtr a, b; applies the pointer to both — the * isn't visibly repeated.
Why doesn't typedef slow your program down?
It resolves entirely at compile time to the original type; the final machine code never mentions the alias, so runtime behaviour and speed are identical.
Why is typedef struct node Node; common in Linked Lists code?
A node struct references itself (struct node *next), and the alias lets every other line write the clean Node while the self-reference inside still uses the not-yet-aliased struct node.

Edge cases

Can you use a typedef name before it appears in the source file?
No. Like a variable, the alias exists only after its declaration; earlier lines don't know the name — it isn't a global macro.
Inside typedef struct node { struct node *next; } Node;, can the next field use Node?
No — at that point in parsing Node isn't defined yet, so the self-reference must use the tag form struct node *next. The alias is only usable after the closing brace.
If two headers both do typedef int Handle;, is including both an error?
In modern C (C11+) redefining a typedef to the same type is allowed and harmless; redefining it to a different type is an error. Guard with include-guards to be safe.
Does typedef work on array types, e.g. typedef int Vec3[3];?
Yes. Then Vec3 v; declares v as int[3]. The array size is part of the alias — but beware: a Vec3 parameter still decays to a pointer, per normal C array rules.
Can you typedef a typedef'd name that itself hides a pointer, and does const behave intuitively?
You can, but const Handle where Handle is int* means "const pointer to int," not "pointer to const int." The const applies to the whole aliased type, which surprises many. See Pointers in C.
Is typedef legal at file scope, block scope, and inside a struct?
File and block scope: yes. Inside a struct body you can declare it too, but its visibility follows the enclosing scope's rules — it does not become a member of the struct.

Recall One-line self-test

Cover every answer above. If any reveal made you say "oh, right" — that was a live misconception. Re-read the matching section of Typedef.


Connections

  • Typedef — the parent topic these traps stress-test.
  • Structures in C — tag-vs-alias namespace traps.
  • Pointers in C — the *-baking and const placement traps.
  • Function Pointers — the missing-* function-pointer trap.
  • Linked Lists — the self-referential struct alias timing trap.