Skip to content

typedef

typedef 是 C 语言中用来给 现有数据类型“别名” (Nickname) 的关键字。

如果说 #define 是简单的“查找替换”,那么 typedef 就是合法的“户口更名”。编译器是真正承认这个新名字的。

它的核心作用就是:让复杂的类型名字变短,让人类更容易看懂。

我们分三个场景来看它的威力:


1. 场景一:偷懒神器 (基本类型)

在单片机开发中,我们经常要写 unsigned char(无符号字符型,0~255)。 这就好比一个人的名字叫“尼古拉斯·赵四”,太长了,写着累。

使用 typedef 起别名:

C

// 给 unsigned char 起个别名叫 u8
typedef unsigned char u8;

// 以后写代码:
u8 data = 10;  // 等同于 unsigned char data = 10;

STM32 中的经典应用: 你是不是经常在代码里看到 uint8_t, uint16_t, uint32_t? 这并不是 C 语言原本就有的关键字,它们其实全都是 typedef 出来的!

stdint.h 头文件里,写着:

C

typedef unsigned char      uint8_t;  // 8位无符号整数 (1字节)
typedef unsigned short     uint16_t; // 16位无符号整数 (2字节)
typedef unsigned int       uint32_t; // 32位无符号整数 (4字节)

好处: 一眼就能看出这个变量占几个字节,比写 intlong 清楚多了(不同编译器下 int 长度可能不同,但 uint32_t 永远是 32 位)。


2. 场景二:结构体救星 (STM32 最常用)

这是 typedef 最重要的用途。

如果不使用 typedef,定义一个结构体变量非常麻烦,必须每次都带上 struct 关键字。

没有 typedef 时 (很啰嗦):

C

struct Student {
    int id;
    int age;
};

// 定义变量时必须加 struct
struct Student xiaoming; 
struct Student xiaohong;

使用 typedef 后 (很清爽):

C

// 语法:typedef 原类型名 新别名;
typedef struct {
    int id;
    int age;
} Student_t;  // Student_t 就是这个结构体的别名

// 定义变量时,不用加 struct 了!
Student_t xiaoming;
Student_t xiaohong;

STM32 库函数就是这么干的: 你常用的 GPIO_InitTypeDef 其实就是一个被 typedef 过的结构体别名。

C

// stm32f10x_gpio.h 里的源码大概是这样的:
typedef struct
{
  uint16_t GPIO_Pin;
  GPIOSpeed_TypeDef GPIO_Speed;
  GPIOMode_TypeDef GPIO_Mode;
} GPIO_InitTypeDef; // 别名

// 所以你能直接写:
GPIO_InitTypeDef GPIO_InitStructure;

3. 场景三:typedef vs #define (面试陷阱)

这是最容易搞混的地方。虽然它们都能起别名,但在处理指针时,区别巨大。

案例:我想定义一个“指向 int 的指针”类型。

C

#define  PTR_D   int* // 宏定义方式
typedef  int* ptr_t;  // typedef 方式

测试代码:

C

PTR_D  a, b;  // 宏展开后变成:int* a, b;
ptr_t  x, y;  // 真正定义:x 和 y 都是指针

结果:

  1. 宏定义 (#define):是纯文本替换。
    • int* a, b; 实际上等价于 int *a; int b;
    • a 是指针,b 只是个普通的整数! (这就出 Bug 了)
  2. typedef:是类型封装。
    • 编译器知道 ptr_t 就是一种指针类型。
    • x 是指针,y 也是指针! (这是我们要的)

总结

  1. 语法:typedef 旧名字 新名字; (注意结尾有分号!)
  2. 作用: 给数据类型起外号,让代码更短、更易读。
  3. STM32 里的体现:
    • uint8_t 代替 unsigned char
    • GPIO_InitTypeDef 代替 struct ...
  4. 原则:
    • 如果是给数字常量起名(如 3.14),用 #define
    • 如果是给数据类型起名(如 struct),必须用 typedef