结构体类型详细讲解(附带枚举,联合)
前言:
如果你还对结构体不是很了解,那么本篇文章将会从 为什么存在结构体,结构体的优点,结构体的定义,结构体的使用与结构体的大小依次介绍,同样会附带枚举与联合体
目录
为什么存在结构体:
结构体的优点
结构体的定义
结构体的使用
方法一:
方法二 函数传值打印
方法三 函数传址打印 两种打印方法
第二种是利用-> 这里的 ->就相当于(*).
方法四 跟方法三差不多,不利用函数打印
结构体的typedef
结构体的大小计算
⾸先得掌握结构体的对⻬规则:
1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。对⻬数=编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。VS 中默认的值为 8
Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3.结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
先解决对其数问题
枚举
枚举的使用案例
联合体(也叫共用体)
为什么存在结构体:
当一个整体由多个数据构成时,于是人们就创造了数组,我们用数组来表示这个整体,但是数组有个特点:内部的每一个元素都必须是相同类型的数据。 ☀ 在实际应用中,我们通常需要由不同类型的数据来构成一个整体,比如学生这个整体可以由姓名、年龄、身高等数据构成,这些数据都具有不同的类型,姓名可以是字符串类型,年龄可以是整型,身高可以是浮点型。 ☀ 为此,C语言专门提供了一种构造类型来解决上述问题,这就是结构体,它允许内部的元素是不同类型的。
结构体的优点
- 可以在一个结构中声明不同的数据类型。
- 相同结构的结构体变量是可以相互赋值的。
- 结构体的存储方式可以提高CPU对内存的访问速度。
- 结构体可以将同一对象的多个数据类型存储在一起,方便数据的存储和处理。
- 可以通过结构体变量名和成员名来访问数据。
- 可以定义结构体数组,方便批量处理数据。
那么有有优点就会有缺点:
- 如果项目的复杂性增加,管理所有数据成员就变得很困难 。
- 对程序中的一个数据结构进行更改需要在其他几个地方进行更改。 所以很难跟踪所有的变化。
- 结构体需要更多的存储空间,因为它为所有数据成员分配内存,甚至速度更慢。
- 结构体占用更多存储空间,因为它为所有不同的数据成员提供内存,而联合仅占用最大数据大小参数所需的内存大小,并且与其他数据成员共享相同的内存。
结构体的定义
一般结构体定义便是如下
struct stu
{//变量成员
};
这里的struct是必不可少的部分,而stu是我们自拟定的,里面便是填充的变量成员
这个结构体就是struct stu类型的
同理下面这个结构体就是struct st类型的
struct st
{//变量成员
};
这时候我们便可以在里面填充成员
比如这样
struct st
{int a;char b;struct st* ps;//也可以填充这个类型的指针
};
那么结构体定义完后,我们开始讲解怎么去使用
结构体的使用
这里的s为变量名
struct st
{int a;char b;
};
int main()
{struct st s = { 10,'b' };//初始化return 0;
}
接下来介绍打印
方法一:
struct st
{int a;char b;
};
int main()
{struct st s = { 10,'b' };//初始化printf("%d %c", s.a, s.b);return 0;
}
方法二 函数传值打印
struct st
{int a;char b;
};
void print(struct st ps)
{printf("%d %c", ps.a, ps.b);
}
int main()
{struct st s = { 10,'b' };//初始化print(s);return 0;
}
方法三 函数传址打印 两种打印方法
第一种的打印是利用解引用
第二种是利用-> 这里的 ->就相当于(*).
struct st
{int a;char b;
};
void print(struct st* ps)
{printf("%d %c\n", (*ps).a, (*ps).b);printf("%d %c\n", ps->a, ps->b);
}
int main()
{struct st s = { 10,'b' };//初始化print(&s);return 0;
}
方法四 跟方法三差不多,不利用函数打印
struct st
{int a;char b;
};
int main()
{struct st s = { 10,'b' };//初始化struct st* ps = &s;printf("%d %c\n", (*ps).a, (*ps).b);printf("%d %c\n", ps->a, ps->b);return 0;
}
结构体的typedef
当一个结构体类型的类型名过于长的时候,我们不免过于不想去写,这时候就可以用typedef
(重命名)使用起来很简单
typedef struct st
{int a;char b;
}st;
int main()
{struct st s = { 10,'b' };//初始化//等价于st s = { 10,'b' };//return 0;
}
结构体的大小计算
先举例一个代码
代码跑出来这个结构体大小是8
那么怎么计算的呢? 其原理就是对其原则
⾸先得掌握结构体的对⻬规则:
1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
2.其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。对⻬数=编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。VS 中默认的值为 8
Linux中gcc没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
3.结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构 体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
我们计算一下这个结构体大小
struct S1
{char c1;int i;char c2;
};
printf("%d\n", sizeof(struct S1))
先解决对其数问题
char 自身对齐数为1 vs上默认对齐数为8 实际取小的 那么最后为1
int 为4
偏移量
在C语言中,偏移量通常指的是结构体中成员变量相对于结构体起始地址的偏移量。假设有一个结构体定义如下:
struct Person {int id;char name[20];int age;
};
假设struct Person p;
是一个Person
类型的结构体变量,我们可以通过&p.id
、&p.name
和&p.age
来获取各个成员变量的地址。偏移量就是从结构体起始地址到成员变量地址的字节偏移量。
例如,假设&p
表示结构体p
的起始地址,&p.id
表示id
成员变量的地址,那么&p.id - &p
就是id
相对于结构体起始地址的偏移量。在C语言中,可以使用指针和强制类型转换来计算偏移量,例如:
int offset = (char *)&p.name - (char *)&p;
这样就可以得到name成员变量相对于结构体p
的偏移量。偏移量在一些底层编程中经常用来访问结构体中的特定成员变量,尤其是在处理二进制数据或者硬件寄存器时非常有用。
画图表示如下
那么我们进行利用图进行计算
typedef struct st
{char c1;int i;char c2;
}st;
int main()
{printf("%zd", sizeof(st));return 0;
}
第一个char偏移量为0放于第一个,int放于偏移量为4的整数倍数处 ,最后一个char偏移量为1,放于1的整数倍数处,
用图表示如下
图上的大小一共占了9个字节,
然后我们进行最后一步 最大对齐数为4 而9不是最大对齐数的整数倍 所以要浪费3个字节补充该结构体大小到12;
那么最大怎么算了就可以解答上面那个问题为什么是8
//练习3
struct S3
{double d;char c;int i;
};
printf("%d\n", sizeof(struct S3));
//练习4-结构体嵌套问题
struct S4
{char c1;struct S3 s3;double d;
};
printf("%d\n", sizeof(struct S4));
答案分别是16 32
枚举
在《C语言深度剖析》这本书中留有一个问题,枚举变量的大小是多少?
大家猜一下大小为多少
enum Color
{GREEN = 1,RED,BLUE,GREEN_RED = 10,GREEN_BLUE,sss,
}c;
int main()
{printf("%zd", sizeof(c));
}
答案是4,为啥呢?
因为,枚举变量的取值为花括号内的任意一个值(有且只能有其中一个值),而这个值是int型的,在X86系统中,int型的数据占内存4个字节。所以sizeof(c) = 4,也就是枚举变量的值为4。
枚举的使用案例
当我们写菜单的时候,会用到switch语句
当我们写case是一般会用到case 1: case 2:
但如果功能一旦多我们就会分不清该case 要实现哪一项功能
这时候就可以用到枚举 就比如通讯录
enum option
{EXIT,//等价于0ADD,//1DEL,//2SEARCH,//3MODIFY,//4SHOW, //5SORT,//6SAVE,//7
};void menu()
{printf("**************************************\n");printf("***** 1.add 2.del *****\n");printf("***** 3.search 4.modify *****\n");printf("***** 5.show 6sort *****\n");printf("***** 7.save 0.exit *****\n");printf("**************************************\n");
}
int main()
{do {menu();printf("请输入你的选择:>");scanf("%d", &input);switch (input){case ADD:Addcontact(&con);break;case DEL:Delcontact(&con);break;case SEARCH:Searchcontact(&con);break;case MODIFY:Modifycontact(&con);break;case SHOW:Showcontact(&con);break;case SORT:SortContact(&con);break;case SAVE:SaveContact(&con);break;case EXIT:SaveContact(&con);DestroyContact(&con);printf("退出通讯录\n");break;default:printf("输入错误,请重新输入:>\n");break;}} while (input);return 0;
}
联合体(也叫共用体)
联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合 ⾄少得有能⼒保存最⼤的那个成员)。
那么看以下代码
发现三者的空间是共用一块空间,所以这也对应了名字共用体,公用一块空间
#include <stdio.h>
union Un
{char c;int i;
};
int main()
{//联合变量的定义 union Un un = {0};un.i = 0x11223344;un.c = 0x55;printf("%x\n", un.i);return 0;
}
既然公用一块空间那么(小端)
这个代码运行结果如何呢?
我们发现将i的第4个字节的内容修改为55了(其实是改的低地址处的数据)
同样大端下会打印55223344;
利用联合体写一个函数判断机器为大端还是小端
int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;//返回1是⼩端,返回0是⼤端
}
相关文章:

结构体类型详细讲解(附带枚举,联合)
前言: 如果你还对结构体不是很了解,那么本篇文章将会从 为什么存在结构体,结构体的优点,结构体的定义,结构体的使用与结构体的大小依次介绍,同样会附带枚举与联合体 目录 为什么存在结构体: 结构…...
编程生活day1--个位数统计、考试座位号、A-B、计算阶乘和
个位数统计 题目描述: 定一个 k 位整数 Ndk−110k−1⋯d1101d0 (0≤di≤9, i0,⋯,k−1, dk−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N100311,则有 2 个 0,3 个 1,和 …...

mysql体系结构及主要文件
目录 1.mysql体系结构 2.数据库与数据库实例 3.物理存储结构编辑 4.mysql主要文件 4.1数据库配置文件 4.2错误日志 4.3表结构定义文件 4.4慢查询日志 4.4.1慢查询相关参数 4.4.2慢查询参数默认值 4.4.3my.cnf中设置慢查询参数 4.4.4slow_query_log参数 4.4.…...

PwnLab靶场PHP伪协议OSCP推荐代码审计命令劫持命令注入
下载链接:PwnLab: init ~ VulnHub 安装: 打开vxbox直接选择导入虚拟电脑即可 正文: 先用nmap扫描靶机ip nmap -sn 192.168.1.1/24 获取到靶机ip后,对靶机的端口进行扫描,并把结果输出到PwnLab文件夹下,命名…...
涉密信息系统集成资质八大类别办理条件是什么?
涉密资质分为八个不同类别,那每个类别的申报条件有哪些?让我们一起来看看吧: 涉密资质申报条件 依据《涉密信息系统集成资质管理办法》的有关规定,申请涉密信息系统集成资质的企事业单位,除符合《涉密信息系统集成资…...
Shell脚本总结-反引号-${}-$()
反引号 反引号的作用就是将输出结果显示出来。 [rootldpbzhaonan bash]$ echo $a ldpbzhaonan${} ${}引用变量,包含自定义的和环境变量。 [rootldpbzhaonan bash]$ a1 [rootldpbzhaonan bash]$ echo ${a} 1$() $()和反引号,返回的是一个指令或者程序…...

Spring MVC入门(4)
请求 获取Cookie/Session 获取Cookie 传统方式: RequestMapping("/m11")public String method11(HttpServletRequest request, HttpServletResponse response) {//获取所有Cookie信息Cookie[] cookies request.getCookies();//打印Cookie信息StringBuilder build…...

RuoYi-Vue-Plus(基础知识点jackson、mybatisplus、redis)
一、JacksonConfig 全局序列化反序列化配置 1.1yml中配置 #时区 spring.jackson.time-zoneGMT8 #日期格式 spring.jackson.date-formatyyyy-MM-dd HH:mm:ss #默认转json的属性,这里设置为非空才转json spring.jackson.default-property-inclusionnon_null #设置属性…...
使用verillog编写KMP字符串匹配算法
设计思路如下: 定义模块的输入输出信号:包括时钟信号clk、复位信号rst、模式串pattern、文本串text以及输出信号match。定义所需寄存器和变量:使用寄存器来存储状态机的状态以及其他控制变量,如模式串数组P、失配函数数组F、模式串位置p_index、文本串位置t_index等。在时钟…...
《每天十分钟》-红宝书第4版-对象、类与面向对象编程(五)
对象迭代 在 JavaScript 有史以来的大部分时间内,迭代对象属性都是一个难题。ECMAScript 2017 新增了两个静态方法,用于将对象内容转换为序列化的——更重要的是可迭代的——格式。这两个静态方法Object.values()和 Object.entries()接收一个对象&#…...

华为ensp中rip动态路由协议原理及配置命令(详解)
CSDN 成就一亿技术人! 作者主页:点击! ENSP专栏:点击! CSDN 成就一亿技术人! ————前言————— RIP(Routing Information Protocol,路由信息协议)是一种距离矢…...

学习要不畏难
我突然发现,畏难心是阻碍我成长的最大敌人。事未难,心先难,心比事都难,是我最大的毛病。然而一念由心生,心不难时,则真难事也不再难。很多那些自认为很难的事,硬着头皮做下来的时候,…...

mysql迁移达梦数据库 Java踩坑合集
达梦数据库踩坑合集 文章目录 安装达梦设置大小写不敏感Spring boot引入达梦驱动(两种方式)将jar包打入本地maven仓库使用国内maven仓库(阿里云镜像) 达梦驱动yml配置springboot mybatis-plus整合达梦,如何避免指定数据库名&…...

arm 解决Rk1126 画框颜色变色问题(RGB转NV12)
在Rv1126上直接对Nv12图像进行绘制时,颜色是灰色。故将Nv12转BGR后绘制图像,绘制完成后转成Nv12,BGR的图像颜色是正常的,但是NV12的图像颜色未画全,如图: 1.排查发现是RGB转NV12的函数出现问题,…...

113 链接集10--ctrl+左键单击多选
1.ctrl左键单击多选,单击单选 精简代码 <div class"model-list"><divmousedown.prevent"handleClick(item, $event)"class"model-list-item"v-for"item in modelList":key"item.id":class"{ model…...

详解JavaScript中this指向
this 原理 this 是一个指针型变量,它指向当前函数的运行环境。 1.内存的数据结构 var obj { foo: 5 };2.函数 var obj { foo: function () {} };引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。 由于函数是一个单独的…...
c语言之在函数中传递指针
c语言中定义一个函数,如果说是形参一个数组,这个数组在编译后会变成一个指针变量 比如下面的代码例子 #include<stdio.h> void ff(char a[]) {a[1]r;a[4]r;printf("%d\n",a); }int main() {char a[]"peogeam";ff(a);printf(…...
vue2 插槽(默认插槽 slot 、具名插槽 v-slot 、作用域插槽 slot-scope -- 插槽传值 )
插槽:用于在子组件的指定位置插入指定内容,类似在电梯里挂的若干广告显示屏,可以给指定的位置传入指定的广告 单插槽(匿名/默认插槽) 父组件中( 此时的 ) <Child><template><p…...
(第79天)单机转 RAC:19C 单机 到 19C RAC
前言 单机转 RAC 分为两种: 同版本迁移:可以使用 RMAN 或者 ADG 方式升级迁移:建议使用数据泵 或者 XTTS 方式升级迁移使用数据泵的方式与 (第72天)数据泵升级:11GR2 到 19C 步骤基本一致,这里不作演示,只演示使用 ADG 来进行同版本迁移。 升级前准备 本次测试尽量按…...
Spring Cloud微服务Actuator和Vue
目录 前言一、引入Actuator依赖二、暴露Actuator端点1. 配置文件2. 监控端点 三、自定义健康检查自定义健康检查类 四、vue前端代码五、监控器的优势六、监控指标的可视化1. Grafana2. Prometheus 七、安全性考虑安全配置示例 八、总结 前言 随着微服务架构的流行,…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...