写代码最烦的就是长类型名。typedef 就是干这个的:给已有类型起个短一点、更贴切的新名字(别名)。结构体、指针、数组这些复杂声明,一下子好读很多。
先看最直接的例子
给 int 起个别名:
typedef int Integer;
int main() {
Integer n = 10; /* n 还是 int,但写起来更像业务语言 */
printf("%d", n); // 10
return 0;
}语法就一句话:
typedef 已有类型 新名字;声明完,新名字就能当原来的类型用了。
给内置类型起别名
长整型的 long long 每次写都嫌长,比赛和算法代码里常缩写:
typedef long long ll;
int main() {
ll a = 20;
printf("%lld", a); // 20
return 0;
}给结构体起别名
这是 typedef 最经典的用法。不用 typedef:
struct Students {
char name[50];
int ID_no;
};
struct Students s; /* 每次都要带 struct 关键字 */用了 typedef:
typedef struct Students {
char name[50];
int ID_no;
} stu; /* stu 就是这个结构体的别名 */
int main() {
stu s; /* 干净利落,不用写 struct */
s.ID_no = 108;
return 0;
}甚至可以把 struct 标签都省掉,直接匿名 + typedef:
typedef struct {
char name[50];
int ID_no;
} stu; /* 以后就用 stu,标签没必要存在 */给指针起别名
typedef int* ip;
int main() {
int a = 10;
ip ptr = &a; /* ptr 是 int* */
printf("%d", *ptr); // 10
return 0;
}给数组起别名
typedef int arr[4]; /* arr 是"int[4]"的别名 */
int main() {
arr a = { 10, 20, 30, 40 }; /* 一个 int[4] 数组 */
for (int i = 0; i < 4; i++)
printf("%d ", a[i]); // 10 20 30 40
return 0;
}函数指针这类更绕的声明也能 typedef 化简(函数指针篇里那种写法,用 typedef 收起来会清爽得多)。
typedef 和 #define 的区别
| typedef | #define |
|---|---|
| 由编译器处理 | 预处理器做纯文本替换 |
| 作用于类型,类型检查友好 | 任何文本都能替换,不做类型检查 |
| 可以在局部作用域声明 | 文件级生效,容易误伤 |
| 不能用来写代码片段/带参替换 | 可以做函数式宏 |
一个经典坑:#define 声明指针别名时只替换文本。
#define intptr int* /* 危险写法 */
intptr a, b; /* 等价于 int* a, b; ,b 其实是 int,不是指针! */
typedef int* intptr2;
intptr2 c, d; /* c、d 都是 int*,类型安全 */这就是为什么给类型起别名,优先用 typedef。
什么时候用 typedef
- 结构体、共用体这类"每次写都带 struct"的长类型。
- 复杂指针、函数指针、数组类型,把声明收成好读的短名。
- 需要统一的跨平台类型(比如
uint32_t这种约定俗成的风格)。
让类型名读起来像业务词汇,而不是一堆符号堆叠,读你代码的人(包括未来的你)会感谢这个选择。