C Typedef
typedef is a keyword in C that creates a new name (an alias) for an existing data type. It does not create a new data type — it simply gives an existing type a different, often shorter or more descriptive name. Using typedef makes your code easier to read, more portable, and simpler to maintain.
Why Use typedef?
Without typedef, some type declarations in C can become long and repetitive — especially for structures, pointers, and function pointers. typedef hides that complexity behind a clean, meaningful name.
// Without typedef — repetitive and verbose
struct Point { int x; int y; };
struct Point p1;
struct Point p2;
// With typedef — clean and short
typedef struct { int x; int y; } Point;
Point p1;
Point p2;
Basic Syntax
typedef existing_type new_name;
Simple Examples
typedef int Integer;
typedef float Decimal;
typedef char Letter;
typedef unsigned long ULong;
Integer age = 25; // same as: int age = 25;
Decimal price = 9.99; // same as: float price = 9.99;
Letter grade = 'A'; // same as: char grade = 'A';
typedef with Structures
The most common use of typedef in C is with structures. Without typedef, you must write struct StructName every time you declare a variable of that type. With typedef, you just write the alias.
Without typedef
#include <stdio.h>
struct Student {
char name[50];
int age;
float marks;
};
int main()
{
struct Student s1; // must write 'struct' every time
struct Student s2;
return 0;
}
With typedef
#include <stdio.h>
typedef struct {
char name[50];
int age;
float marks;
} Student; // 'Student' is now the type name
int main()
{
Student s1; // no 'struct' keyword needed
Student s2;
s1.age = 20;
s1.marks = 85.5;
printf("Age: %d, Marks: %.1f\n", s1.age, s1.marks);
return 0;
}
typedef with Pointers
typedef can simplify pointer declarations — especially when working with pointers that appear many times in a program.
typedef int* IntPtr;
IntPtr a, b; // both a and b are int pointers
// Equivalent to: int *a, *b;
Caution: typedef int* IntPtr; IntPtr a, b; makes both a and b pointers. But int* a, b; only makes a a pointer — b would be a regular int. typedef avoids this ambiguity.
#include <stdio.h>
typedef int* IntPtr;
int main()
{
int x = 10;
IntPtr ptr = &x;
printf("Value: %d\n", *ptr); // Output: 10
return 0;
}
typedef with Function Pointers
Function pointer syntax is notoriously complex. typedef makes it manageable.
// Without typedef — hard to read
int (*mathFunc)(int, int);
// With typedef — readable
typedef int (*MathFunc)(int, int);
MathFunc add;
MathFunc multiply;
#include <stdio.h>
typedef int (*Operation)(int, int); // Operation is now an alias for this function pointer type
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int main()
{
Operation op;
op = add;
printf("Add: %d\n", op(10, 5)); // Output: Add: 15
op = sub;
printf("Sub: %d\n", op(10, 5)); // Output: Sub: 5
return 0;
}
typedef with Arrays
typedef int Matrix[3][3]; // Matrix is a 3x3 int array type
Matrix identity = {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1}
};
typedef for Portability
On different platforms, the size of basic types like int may differ. typedef is used in system headers to define types with guaranteed sizes.
// From <stdint.h> (part of C99 standard)
typedef unsigned char uint8_t; // always 8 bits
typedef unsigned short uint16_t; // always 16 bits
typedef unsigned int uint32_t; // always 32 bits
typedef unsigned long long uint64_t; // always 64 bits
// Using these in code ensures consistent behavior across platforms
uint8_t byte = 255;
uint32_t count = 1000000;
Practical Example: Building a Contact Book
#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
char phone[15];
char city[30];
} Contact;
void printContact(Contact c)
{
printf("Name : %s\n", c.name);
printf("Phone: %s\n", c.phone);
printf("City : %s\n", c.city);
printf("---\n");
}
int main()
{
Contact book[2];
strcpy(book[0].name, "Alice");
strcpy(book[0].phone, "9876543210");
strcpy(book[0].city, "Delhi");
strcpy(book[1].name, "Bob");
strcpy(book[1].phone, "9123456789");
strcpy(book[1].city, "Mumbai");
for (int i = 0; i < 2; i++)
printContact(book[i]);
return 0;
}
Output:
Name : Alice
Phone: 9876543210
City : Delhi
---
Name : Bob
Phone: 9123456789
City : Mumbai
---
typedef vs #define
| Feature | typedef | #define |
|---|---|---|
| Processed by | Compiler | Preprocessor |
| Type checking | Yes — respects type rules | No — just text replacement |
| Scope | Follows C block scoping | Global from definition point |
| Pointer alias clarity | Yes — all declared variables are pointers | No — only the first gets * |
| Works with structures | Yes — creates clean aliases | Limited, no real type name |
Common typedef Patterns
// Boolean type (before C99 _Bool)
typedef int bool;
#define true 1
#define false 0
// String alias
typedef char* String;
String message = "Hello, World!";
// Size type
typedef unsigned int size_t;
Summary
The typedef keyword creates an alias for an existing data type, making code more readable and maintainable. It does not create a new type — it only gives the existing type a new name. typedef shines when used with structures (removing the need to write struct repeatedly), pointers (clarifying that all declared variables are pointers), and function pointers (simplifying complex declarations). Standard C libraries use typedef extensively for portable types like uint8_t and size_t. Compared to #define, typedef is processed by the compiler with proper type checking, making it the safer and preferred choice for creating type aliases in C programs.
