【自定义类型】带你走进结构体、枚举、联合(下)

简介: 【自定义类型】带你走进结构体、枚举、联合(下)

1.7修改默认对齐数

我们可以使用 #pragma 这个预处理指令,改变默认对齐数(默认对齐数在不同的编译器中有所不同)

#pragma pack(num)        修改默认偏移量为num

#pragma pack ()              表示,取消之前设置的默认偏移量,回到编译器默认偏移量

代码演示:

#pragma pack(4)//设置默认对齐数为4
struct s3 {
  char c1;
  int i;
  char c2;
  double c;
};
#pragma pack()//再次使用这个预处理宏,会取消设置的默认对齐数
#pragma pack(1)//设置最大对齐数为1
struct s4 {
  char c1;
  int i;
  char c2;
  double c;
};
int main()
{
  printf("%d ", sizeof(struct s3));
  printf("%d", sizeof(struct s4));
  return 0;
}

所以说在学会使用#pragma pack(),就可以在结构对齐方式不合适时,自己更改默认对齐数

1.8结构体传参

我们有两种方式可以传参,第一传结构体,第二传地址,哪一个更好呢?

代码演示:

//传参:1.传递结构体,2.传递地址
struct s3 {
  int data;
};
struct s3 s = { 1000 };
void print1(struct s3 s)//传递结构体
{
  printf("%d  ", s.data);
}
void print2(struct s3* s) {//传递地址
  printf("%d", s->data);
}
int main() {
  print1(s);//传递结构体
  print2(&s);//传递地址
}

两种方法,由于传递地址,不会在创建形参的时候,再次申请空间,而且结构体的内存一般比较大,所以为了更好的节约开销,我们比较倾向于传地址

1.函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。

2.如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导     致性能的下降

二、枚举

1.枚举的定义

枚举就是一一列举各种可能性

把可能取值都一一列举出来,比如一周七天,所以可以列举出来星期一、星期二....

代码演示 :

enum Day//星期
{
Mon,
Tues,   //枚举成员之间使用逗号隔开
Wed,
Thur,
Fri,
Sat,
Sun   //且枚举的成员的取值是从0开始的,逐渐+1
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED,
GREEN,
BLUE
};
int main()
{
  printf("%d\n", Mon);
  printf("%d\n", Tues);
  printf("%d\n", Wed);
  printf("%d\n", Thur);
  printf("%d\n", Fri);
  printf("%d\n", Sat);
  printf("%d\n", Sun);
  return 0;
}

图文演示:

以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。

{}中的内容是枚举类型的可能取值,也叫 枚举常量 。

这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值

enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};

2.枚举的优点

为什么要使用枚举,出现枚举enum这样一个类似与结构体的东西?

有些小伙伴看出来了 枚举不就是一个对于 #define 定义常量的集合吗,那么创建枚举的意思是?

好处是什么?

枚举的优点:

1. 增加代码的可读性和可维护性
2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量

3.枚举的使用

我们到现在,了解认识了枚举的定义,什么是枚举,枚举的优点是什么?最后来认识一下,如何使用枚举,怎么正确使用?

图文演示:

三、联合(共用体

1.联合的定义

联合是一种特殊的自定义类型

这种类型定义的变量,也是和结构体类似,有一系列的成员,特征是这些成员公共使用同一块空间

比如:

联合其实就是,共同使用一个空间,改变一个成员变量的时候,另一个成员变量也可能会改变,这个比较适合,一个使用,其他不适用的情况。

2.联合的特点

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小因为联合至少得有能力保存最大的那个成员)。

那么就来看看,联合里面的成员的首地址是什么?是不是一样的?

代码演示:

3.联合大小的计算

上文我们了解到了,结构体内存大小计算是有很多项规定的,是否感觉计算起来确实有点麻烦,那么联合就很简单啦。只有俩个点

1.联合的大小至少是最大成员的大小。    

2.当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

第一种情况:

( 就是说谁最大,就用谁,没有数组,结构体的时候,只有基本内置类型的时候

这样大小就是其中最大的类型 的字节大小

第二种情况:

代码演示:

union un1 {
  char c[5];//5个char类型为5字节
  int i;//;两种类型int char 所以最后结果为4 的倍数
  //5>4  所以最后为8
};
union un2 {
  short c[7];//相当于7个short类型连着  这样是14个字节
  int i;//un2 中 类型一共两种  int short  所以int为最大类型,所以最后得到的数据应该是4的倍数
  //因为是联合 所以14是这两个联合起来其中最大的一个, 再取4的倍数 ,得到16
};
int main()
{
  printf("%d\n", sizeof(union un1));//8
  printf("%d\n", sizeof(union un2));//16
  return 0;
}

4.练习题

如何检验当前编译器是大小端问题

之前我们学指针的时候,学到了第一种方法,请参考大小端【C语言进阶】深度剖析数据在内存中的存储_小王学代码的博客-CSDN博客

接下来我们来看用联合如何测试?

代码如下:

所以得到,在VS环境下为小端。


总结

我们在这一章节学到了结构体的定义,如何声明,自引用,结构体变量的定义和初始化,结构体内存对齐,还有如何修改默认对齐数。接着对于枚举的认识,和使用、最后是联合的定义特点以及如何计算大小问题,以一道面试题来结束本文。

希望大家在看完这篇文章的时候,会对你有所启发,虽然枚举、联合现阶段用的很少,但是我们一定要了解,并认识,结构体的内容是很重要的,自引用的合理使用,会在数据结构的时候频繁使用!!

最后你的留言,你的点赞收藏都是小王前进的动力,欢迎大佬指点,有所不足,请您指出,谢谢!!!

相关文章
|
3天前
|
数据采集 人工智能 安全
|
12天前
|
云安全 监控 安全
|
4天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
1045 151
|
4天前
|
编解码 人工智能 机器人
通义万相2.6,模型使用指南
智能分镜 | 多镜头叙事 | 支持15秒视频生成 | 高品质声音生成 | 多人稳定对话
|
17天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1732 9
|
9天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
682 152
|
11天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
646 12
|
6天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
408 4