C 语言 typedef 的用法
一、typedef 是什么
typedef是类型别名关键字,作用:给已存在的数据类型起一个新名字,不会创建新类型,只是原有类型的别名。 语法格式:
typedef 原类型 新类型名;二、基础用法(简单内置类型)
1. 基础数据类型简化
#include <stdio.h> // 给int起别名Integer typedef int Integer; // 无符号整型别名 typedef unsigned int Uint; // 长整型别名 typedef long long ll; int main() { Integer a = 10; Uint b = 100; ll c = 9999999999; printf("%d %u %lld", a, b, c); return 0; }2. 指针类型别名
普通指针
typedef int* PInt; int main() { int x = 5; PInt p = &x; // PInt等价int* *p = 10; return 0; }易错点:typedef 指针和宏定义区别
#define P_INT int* typedef int* PInt; P_INT a, b; // 等价 int* a; int b; 宏单纯文本替换 PInt c, d; // 等价 int *c, *d; 全部都是指针重点:typedef会把整个类型绑定,宏只是文本替换,这是最常踩坑点。
三、结构体搭配 typedef(最常用场景)
C 语言原生结构体使用必须带struct关键字,typedef可以省略。
1. 标准写法
// 先定义结构体,再起别名 struct Student { char name[20]; int age; }; typedef struct Student Stu; Stu s1; // 不用写struct Student2. 一步简写(工程最常用)
typedef struct { char name[20]; int age; } Stu; Stu s2;结构体指针别名
typedef struct { int id; } Node, *PNode; // Node = 结构体类型 // PNode = 结构体指针 Node* Node n; PNode p = &n;四、数组类型别名
1. 固定长度数组
// 长度100的int数组别名 Arr100 typedef int Arr100[100]; Arr100 arr; // 等价 int arr[100]; arr[0] = 1;2. 函数参数数组简化
typedef int Vector[5]; void print(Vector v) { for(int i=0;i<5;i++) printf("%d ",v[i]); } int main() { Vector v = {1,2,3,4,5}; print(v); return 0; }五、函数指针 typedef(复杂场景核心)
函数指针语法极繁琐,typedef是最佳简化方案。
1. 普通函数指针别名
// 原函数:int calc(int a, int b); // 给“接收两个int、返回int的函数”起别名 Func typedef int (*Func)(int, int); int add(int a, int b) { return a + b; } int sub(int a, int b) { return a - b; } int main() { Func f1 = add; Func f2 = sub; printf("%d", f1(10,20)); return 0; }2. 回调函数、结构体中存储函数指针
typedef void (*Callback)(int); void printNum(int x) { printf("%d", x); } typedef struct { Callback cb; // 结构体存放回调函数 } Task; int main() { Task t; t.cb = printNum; t.cb(666); return 0; }六、枚举类型 typedef
省去每次写enum
typedef enum { RED, GREEN, BLUE } Color; Color c = RED;七、const 和 typedef 组合(难点)
typedef别名是完整类型,const修饰规则和直接写原生类型不同。
typedef int* PInt; const PInt p; // 等价 int *const p; 指针本身不可修改,指向的值可改 // 不是 const int *p int a = 1, b = 2; const PInt p = &a; *p = 100; // 合法 p = &b; // 报错,指针只读拆解:PInt = int*const PInt = const (int*) = int *const
八、typedef 作用与优势
1. 简化复杂类型:函数指针、多层结构体、长类型名大幅精简代码
2. 提升可读性:PNode、Callback语义清晰,比裸指针好理解
3. 便于跨平台移植:
// 不同平台long长度不同,统一别名 typedef long long Int64; typedef int Int32;更换平台时只需修改 typedef 一行,不用全局改所有变量。
4. 省略关键字:struct /enum 不用每次重复书写
九、typedef 和 #define 的核心区别
| 特性 | typedef | #define |
|---|---|---|
| 本质 | 编译器识别的类型别名 | 预处理器文本简单替换 |
| 指针处理 | typedef int* P; P a,b;两个都是指针 | #define P int*; P a,b;仅 a 是指针 |
| const 绑定 | 整体类型生效 | 单纯文本替换,易出错 |
| 作用域 | 遵循 C 作用域(局部 / 全局) | 全局生效,无作用域限制 |
typedef char* Str; #define STR char* Str s1, s2; // char *s1, *s2; STR s3, s4; // char *s3; char s4;十、综合实战示例(链表标准写法)
工程中最经典的 typedef 结构体 + 指针用法:
#include <stdio.h> #include <stdlib.h> // 链表节点+节点指针一步定义 typedef struct Node { int data; struct Node *next; } Node, *List; // 创建新节点 List createNode(int val) { List newNode = (List)malloc(sizeof(Node)); newNode->data = val; newNode->next = NULL; return newNode; } int main() { List head = createNode(10); printf("%d", head->data); return 0; }十一、常见误区总结
- typedef 不生成新类型,只是别名,
typedef int A; int和A完全等价 - 不要用宏代替 typedef 定义指针、数组、函数类型,极易出错
const修饰 typedef 指针时,只读作用在指针本身,不是指向内容- 函数指针 typedef 括号不能省略:
typedef int (*F)();,少括号会变成返回指针的函数
