当前位置: 首页 > news >正文

C结构体的几种定义形式 + typedef结合使用的好处

struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下:

        struct tag 
        {
                    member-list
                    member-list
                    member-list  
                    ...

        } variable-list ;

tag 是结构体标签。

member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。

variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。

在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。以下为实例:

 C 结构体 | 菜鸟教程(<----摘抄了一部分菜鸟的C教程,这里链接给一下)

一、基本的结构体定义 (不使用 typedef)

1. 声明了 结构体标签;不声明结构体变量。(方式1)

struct  结构体标签  {数据类型  成员1;数据类型  成员2;// ... 更多成员
};

这种是结构体最常用也是最基本的定义方式。

struct: 关键字,表示定义一个结构体。

结构体标签: 给这个结构体类型起的名字 (类似于盒子的名字)。 你以后可以靠这个标签来声明这个类型的变量。

{ ... }: 花括号里定义一个个“成员”(类似于盒子里的每一个积木)。每个成员都有自己的数据类型(比如 intfloatchar)和名称。

//使用举例:
struct Point 
{ int x; int y; 
}; // 声明一个Point类型的变量(创建了一个盒子) 
struct Point p1; //每次声明变量的时候,都需要加上 struct 关键字。
p1.x = 10; // 访问成员 
p1.y = 20; // 访问成员 

特点: 每次声明变量的时候,都需要加上 struct 关键字。

2. 声明了 结构体变量;不声明 结构体标签。(方式2)

struct {数据类型  成员1;数据类型  成员2;// ...
} 变量名;

这种方式 没有结构体标签,它直接定义一个匿名结构体的变量。 创建一个盒子,并给这个盒子装上东西,但是没有给盒子起名字。

//使用举例:
struct {int x;int y;
} p5; // 定义了一个匿名的结构体变量 p5p5.x = 70;
p5.y = 80;// 再次定义会报错,因为结构体“长相”不同
// struct {
//   int x;
//   int y;
// } p6;  // 错误!

特点: 只能在定义的时候创建变量。 无法再创建同类型的其他变量,因为没有结构体标签来指示类型。 通常很少使用。

 

3. 同时声明了 结构体变量 和 结构体标签。(方式3)

struct 结构体标签 
{ 数据类型 成员1; 数据类型 成员2; // ... 更多成员 
}变量名;

解释: 同时定义了结构体标签P2和结构体变量S2。后续可以再通过结构体标签 P2,再定义S3,S4之类的结构体变量(struct P2 S3,S4;),可以理解其走了两步,第一步为:struct P2

{ int a; char b; double c; };  第二步为:struct P2 S2;

1. .h 文件中直接定义这种形式,在编译中不通过,这种形式同时完成了结构体声明和结构体定义,想象一下,如果你把 struct P2 S2; 放在一个 .h 文件里,并被多个 .c 文件 #include 了。 那么,每个包含这个 .h 文件的 .c 文件都会试图创建变量 S2。 这会导致 重复定义错误 (编译器会报错,因为同一个变量被多次定义了)。

2.可以放在某个.c文件中编译通过;

二、与 typedef联合使用

1.  使用 typedef 定义结构体 (带标签)(方式4)

typedef struct 结构体标签 {数据类型  成员1;数据类型  成员2;// ...
} 新的类型名;/*typedef 
struct 结构体标签 {数据类型  成员1;数据类型  成员2;// ...
} 
别名;*/

typedef: 关键字,用于给一个数据类型(包括结构体)起个别名。

新的类型名: 你给这个结构体类型新起的名字 (类似于给盒子起个外号)。 以后可以用这个新的名字来声明变量,而不需要写 struct 了。

typedef struct  Point  {  // 这个结构体叫 Point,并且起了一个"别名" MyPointint x;int y;
} MyPoint;// 声明一个Point类型的变量(创建了一个盒子)
MyPoint p2;  // 不需要写 "struct" 了!
p2.x = 30;
p2.y = 40;

特点:以后声明变量时,可以直接使用新起的类型名。更简洁,更方便。 推荐使用 typedef 来定义结构体。

2. 使用 typedef 定义匿名结构体 (无标签)(方式5)

typedef struct {数据类型  成员1;数据类型  成员2;// ...
}  新的类型名;

这种定义方式 没有结构体标签。 这样定义的结构体只能通过 typedef 赋的别名来使用。

//使用举例:
typedef struct {  // 没有 "结构体标签"int x;int y;
} MyPoint;  // 定义结构体的时候同时定义了别名MyPoint p3;
p3.x = 50;
p3.y = 60;// 错误,因为没有定义结构体名称
// struct { int x; int y; } p4;  // 错误!

    特点: 只能使用 typedef 定义的别名来声明变量。 因为没有结构体标签,所以无法再用 struct { ... } 变量名; 这种方式定义变量。

    3.在结构体定义时就进行初始化 (配合 typedef 与否均可)

    解释: 在定义结构体变量的同时,给它的成员赋值。

    3.1使用 typedef

    typedef struct Point {int x;int y;
    } MyPoint;MyPoint p1 = {100, 200};  // 直接初始化
    

    3.2不使用 typedef

    struct Point {int x;int y;
    };struct Point p2 = {300, 400};
    

    总结:
    • 推荐: 使用 typedef 结合结构体标签。 这样既可以给结构体起别名,又方便以后阅读和维护代码。

    • 一般避免: 直接定义匿名结构体变量(方式2)。 因为你很难重复使用这个类型。

    • 匿名结构体: 适合在定义后立即使用,并且不希望再定义同类型结构体的情况。 比较少见。

    http://www.dtcms.com/a/316151.html

    相关文章:

  1. 数分思维14:用户研究与数据分析
  2. WordPress如何实现隐藏文章部分内容?WordPress无法解析[hide]...[/hide]这类短代码怎么办?
  3. 【机器学习】算法调参的两种方式:网格搜索(枚举)、随机搜索
  4. Android 中几种常用布局的优缺点
  5. 2023 年 6 月 GESP Python 二级试卷真题+答案+解析
  6. 基于 Lyapunov 能量函数的等势面绘制方法 —— MATLAB 实现与工程应用拓展
  7. 永磁同步电机的矢量控制
  8. CPP引用
  9. 组织架构与软件架构协同演进实践指南
  10. UE5 安装Visual Studio
  11. Go语言实战案例:使用context控制协程取消
  12. GB28181监控平台LiveGBS如何配置GB28181对接海康、大华解码器上墙,将GB28181平台是视频给硬件解码器解码上墙
  13. 软件无线电 招标参数
  14. ⭐CVPR2025 非均匀运动视频插帧新突破
  15. 文献阅读 | Briefings in Bioinformatics | Hiplot:全面且易于使用的生物医学可视化分析平台
  16. HarmonyOS 应用拉起系列(二):如何拉起微信小程序
  17. 前端1.0
  18. 查看 Redis 某个数据库的内存占用
  19. python+MySQL组合实现生成销售财务报告
  20. 站在前端的角度,看鸿蒙页面布局
  21. MTK-Android 系统拷贝预置资源
  22. 本地使用uv管理的python项目怎么部署到服务器?
  23. Next.js 链接与导航:页面间无缝切换
  24. 最新安卓原生对接苹果cms App后端+app(最新优化版)
  25. Spring Cloud系列—简介
  26. 从循环嵌套到拓扑编排:LangGraph如何重构Agent工作流
  27. 网络 —— 笔记本(主机)、主机虚拟机(Windows、Ubuntu)、手机(笔记本热点),三者进行相互ping通
  28. 企业AI转型之战:Coze、Dify与FastGPT的巅峰对决
  29. css动态样式
  30. Linux 内存管理之 Rmap 反向映射(二)