【C语言】结构体typedef struct与struct的区别

这两种写法本质上都是定义结构体类型 ,但在 C 语言中有一些重要区别,主要体现在类型名、标签名(tag)、作用域和兼容性。


1. 第一种写法

c 复制代码
typedef struct {

} xxx_t;

这是:

定义一个匿名结构体,并给它起一个类型别名 xxx_t

等价于:

c 复制代码
struct <匿名> {
    
};

typedef struct <匿名> xxx_t;

但是这个结构体没有名字(tag)。

使用:

c 复制代码
xxx_t a;

可以。

但是:

c 复制代码
struct xxx_t b;

不可以。

因为根本不存在 struct xxx_t 这个类型。


例如:

c 复制代码
typedef struct {
    int age;
    char name[20];
} person_t;


person_t p1;   // 正确

struct person_t p2;  // 错误

2. 第二种写法

c 复制代码
struct xxx_t {

};

typedef struct xxx_t xxx_t;

这里做了两件事:

第一步:

定义一个有名字的结构体标签:

c 复制代码
struct xxx_t {

};

第二步:

给它定义一个别名:

c 复制代码
typedef struct xxx_t xxx_t;

所以现在有两个名字:

名字 含义
struct xxx_t 结构体标签名
xxx_t typedef类型名

两个都可以使用:

c 复制代码
struct xxx_t a;

xxx_t b;

都合法。


3. 最大区别:前向声明

这是工程中最重要的区别。

例如链表:

c 复制代码
typedef struct node_t
{
    int data;
    struct node_t *next;

} node_t;

这里必须使用第二种。

为什么?

因为结构体里面包含自己:

c 复制代码
struct node_t *next;

编译器需要提前知道:

存在一个叫 node_t 的结构体


如果写:

c 复制代码
typedef struct {

    int data;
    struct xxx_t *next;

} xxx_t;

会失败。

因为:

c 复制代码
struct xxx_t

根本不存在。


4. 嵌套结构体引用区别

例如:

匿名结构体

c 复制代码
typedef struct
{
    int x;
} point_t;

只能:

c 复制代码
point_t p;

不能:

c 复制代码
struct point_t p;

有标签结构体

c 复制代码
typedef struct point_t
{
    int x;
} point_t;

可以:

c 复制代码
point_t p1;

struct point_t p2;

5. 实际工程推荐写法

在嵌入式项目(STM32、FreeRTOS等)中,一般推荐:

c 复制代码
typedef struct
{
    uint8_t id;
    float temperature;
    uint32_t timestamp;

} SensorData_t;

适合:

  • 数据结构
  • 配置结构
  • 参数结构

例如:

c 复制代码
SensorData_t sensor;

简洁。


对于可能扩展、需要互相引用的结构体,推荐:

c 复制代码
typedef struct Device_t Device_t;

struct Device_t
{
    uint8_t id;
    Device_t *parent;
};

或者:

c 复制代码
typedef struct Device_t
{
    uint8_t id;
    struct Device_t *parent;

} Device_t;

适合:

  • 链表
  • 树
  • 驱动对象
  • C语言面向对象写法

例如很多 HAL 驱动:

c 复制代码
typedef struct
{
    SPI_HandleTypeDef *hspi;
    uint8_t state;

} SPI_Device_t;

或者:

c 复制代码
typedef struct UART_Device UART_Device;

struct UART_Device
{
    UART_Device *next;
    void (*send)(UART_Device *);
};

总结

区别 typedef struct{} xxx_t struct xxx_t{}; typedef ...
结构体是否有名字 ❌匿名 ✅有tag
能否写 struct xxx_t ❌不能 ✅可以
能否自引用 ❌困难 ✅可以
代码简洁 ✅更简洁 稍复杂
适合普通数据结构 ✅ ✅
适合链表/对象模型 ❌ ✅

在 STM32 驱动、FreeRTOS、协议栈这类大型 C 工程里,我更推荐第二种:

c 复制代码
typedef struct xxx_t xxx_t;

struct xxx_t
{
    ...
};

扩展性更好。对于简单的数据包、配置参数,第一种更常见。

相关推荐
滕州市燕猫虎计算机科技工作室个体工商户19 分钟前
Java,Java NIO,Java NIO2,Java AIO,AsynchronousServerSocketChannel
java·开发语言·nio·aio·nio2
古城小栈25 分钟前
Rust 学习路线,供初学者参考
开发语言·rust
喵了几个咪30 分钟前
GoWind CMS 拆解:给 NL2SQL 上四把锁——智能问数的安全边界
开发语言·后端·安全·微服务·golang·gowind
多弗朗皮卡丘32 分钟前
C++的类型转换
开发语言·c++
FLJwu1 小时前
运动相机图像传感器选型实战|第二篇:参数看着一模一样,为什么骑行录像疯狂果冻、拖影翻车?
android·c语言·开发语言·数码相机·运动相机·oem 量产
驭渊的小故事1 小时前
从 JVM 底层看泛型:泛型擦除、Signature 属性与 Super Type Token 模式
java·开发语言·jvm
Escalating_xu1 小时前
【C语言项目实战】贪吃蛇(下):移动、碰撞与计分,完成一局可玩的游戏
c语言·开发语言·游戏
qq_401700412 小时前
Qt Modbus 源码剖析:从 QModbusClient 到工业级通信框架
开发语言·qt·系统架构
星夜离尘562 小时前
MATLAB 角度解缠遇到丢样:先分段,再说明圈数为什么不可恢复
开发语言·matlab
我命由我123452 小时前
6-2.Python 异常处理 - 异常捕获(捕获指定异常、常见异常类型、异常信息)
java·运维·开发语言·python·http·https·java-ee