C语言第三十弹---自定义类型:结构体(上)

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】

结构体

1、结构体类型的声明

1.1、结构体回顾

1.1.1、结构的声明

1.1.2、结构体变量的创建和初始化

1.2、结构的特殊声明

1.3、结构的自引用

2、结构体内存对齐

2.1、对齐规则

​编辑

总结


1、结构体类型的声明

前面我们在学习操作符的时候,已经学习了结构体的知识,这里稍微复习⼀下。

1.1、结构体回顾

结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

1.1.1、结构的声明

struct tag
{member-list;//成员列表
}variable-list;//全局变量列表
例如描述⼀个学生:
struct Stu
{char name[20];//名字int age;//年龄char sex[5];//性别char id[20];//学号
}; //分号不能丢

1.1.2、结构体变量的创建和初始化

#include <stdio.h>
struct Stu
{char name[20];//名字int age;//年龄char sex[5];//性别char id[20];//学号
};
int main()
{//按照结构体成员的顺序初始化struct Stu s = { "张三", 20, "男", "20230818001" };printf("name: %s\n", s.name);printf("age : %d\n", s.age);printf("sex : %s\n", s.sex);printf("id : %s\n", s.id);//按照指定的顺序初始化struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex = "⼥printf("name: %s\n", s2.name);printf("age : %d\n", s2.age);printf("sex : %s\n", s2.sex);printf("id : %s\n", s2.id);return 0;
}

1.2、结构的特殊声明

在声明结构的时候,可以不完全的声明。
比如:
//匿名结构体类型
struct
{int a;char b;float c;}x;
struct
{int a;char b;float c;
}a[20], *p;
上面的两个结构在声明的时候省略掉了结构体标签(tag)。
那么问题来了?
//在上⾯代码的基础上,下⾯的代码合法吗?
p = &x;
警告:
编译器会把上面的两个声明当成完全不同的两个类型,所以是非法的。
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使用⼀次。

1.3、结构的自引用

在结构中包含⼀个类型为该结构本身的成员是否可以呢?
比如,定义⼀个链表的节点
struct Node
{int data;struct Node next;
};
上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?
仔细分析,其实是不行的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的大小就会无穷的大,是不合理的。
正确的自引用方式:
struct Node
{int data;struct Node* next;
};
在结构体自引用使用的过程中,夹杂了 typedef 对匿名结构体类型重命名,也容易引入问题,看看
下面的代码,可行吗?
typedef struct
{int data;Node* next;
}Node;
答案是不行的,因为 Node是对前面的匿名结构体类型的重命名产生的,但是在匿名结构体内部提前使用Node类型来创建成员变量,这是不行的。
解决方案如下:定义结构体不要使用匿名结构体了
typedef struct Node
{int data;struct Node* next;
}Node;

2、结构体内存对齐

我们已经掌握了结构体的基本使用了。
现在我们深入讨论⼀个问题:计算结构体的大小。
这也是⼀个特别热门的考点: 结构体内存对齐

2.1、对齐规则

首先得掌握结构体的对齐规则:
1. 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。
3. 结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。
- VS 中默认的值为 8
- Linux中 gcc 没有默认对齐数,对齐数就是成员自身的大小
//练习1
struct S1
{char c1;int i;char c2;
};
printf("%d\n", sizeof(struct S1));

1、根据结构体对齐的规则,结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处,即上图第一个绿色框。

2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。int 类型对齐数为4,VS默认对齐数为8,因此对齐到4的整数倍,即上图橙色方框。

3、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。char 类型对齐数为1,VS默认对齐数为8,因此对齐到1的整数倍,即上图蓝色方框。

4、结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的整数倍。最大对齐数为4,此时结构体大小9不是4的倍数,因此会再在多浪费3个字节(上图x是浪费的空间),因此大小为12字节。

//练习2
struct S2
{char c1;char c2;int i;
};
printf("%d\n", sizeof(struct S2));

1、根据结构体对齐的规则,结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处,即上图第一个绿色框。

2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。char 类型对齐数为1,VS默认对齐数为8,因此对齐到1的整数倍,即上图橙色方框。

3、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。char 类型对齐数为1,VS默认对齐数为8,因此对齐到1的整数倍,即上图蓝色方框。

4、结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的整数倍。最大对齐数为4,此时结构体大小8是4的倍数,因此大小为8字节。

//练习3
struct S3
{double d;char c;int i;
};
printf("%d\n", sizeof(struct S3));

1、根据结构体对齐的规则,结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处,即上图第一个绿色框。

2、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。char 类型对齐数为1,VS默认对齐数为8,因此对齐到1的整数倍,即上图橙色方框。

3、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。int 类型对齐数为4,VS默认对齐数为8,因此对齐到4的整数倍,即上图蓝色方框。

4、结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的整数倍。最大对齐数为8,此时结构体大小16是8的倍数,因此大小为16字节。

//练习4-结构体嵌套问题
struct S4
{char c1;struct S3 s3;double d;
};
printf("%d\n", sizeof(struct S4));

1、根据结构体对齐的规则,结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处,即上图第一个绿色框。

2、如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。double 类型对齐数为8,VS默认对齐数为8,因此对齐到8的整数倍,即上图橙色方框。

3、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。char 类型对齐数为1,VS默认对齐数为8,因此对齐到1的整数倍,即上图蓝色方框。

4、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。int 类型对齐数为4,VS默认对齐数为8,因此对齐到4的整数倍,即上图绿色方框。

5、其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。double 类型对齐数为8,VS默认对齐数为8,因此对齐到8的整数倍,即上图橙色方框。

6、结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。最大对齐数为8,此时结构体大小32是8的倍数,因此大小为32字节。

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2808249.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

未来已来:数字孪生与智慧园区的深度融合

目录 一、数字孪生技术的概述 二、智慧园区的概念和发展 三、数字孪生与智慧园区的深度融合 四、数字孪生与智慧园区的未来展望 五、结论 随着科技的飞速发展&#xff0c;我们正处在一个日新月异的时代。数字孪生技术作为新兴的前沿科技&#xff0c;已经引起了全球范围内的…

【人脸朝向识别与分类预测】基于PNN神经网络

课题名称&#xff1a;基于PNN神经网络的人脸朝向识别分类 版本日期&#xff1a;2024-02-20 运行方式&#xff1a;直接运行PNN0503.m文件 代码获取方式&#xff1a;私信博主或 QQ:491052175 模型描述&#xff1a; 采集到一组人脸朝向不同角度时的图像&#xff0c;图像来自不…

奇异递归模板模式应用6-类模板enable_shared_from_this

异步编程中存在一种场景&#xff0c;需要在类中将该类的对象注册到某个回调类或函数中&#xff0c;不能简单地将this传递给回调类中&#xff0c;很可能因为回调时该对象不存在而导致野指针访问&#xff08;也有可能在析构函数解注册时被回调&#xff0c;造成对象不完整&#xf…

[VNCTF2024]-Web:CheckIn解析

查看网页 一款很经典的游戏&#xff0c;而且是用js写的 在调试器里面我们可以看见&#xff0c;如果游戏通关的话&#xff0c;它会进行一系列操作&#xff0c;包括使用console.log(_0x3d9d[0]);输出_0x3d9d[0]到控制台&#xff0c;那我们就直接在点击在控制台求出它的值

初始Nginx(基本概念)

目录 一、Nginx的概念 二、Nginx常用功能 1、HTTP(正向)代理&#xff0c;反向代理 1.1正向代理 1.2 反向代理 2、负载均衡 2.1 轮询法&#xff08;默认方法&#xff09; 2.2 weight权重模式&#xff08;加权轮询&#xff09; 2.3 ip_hash 3、web缓存 三、基础特性 四…

论文阅读:Ground-Fusion: A Low-cost Ground SLAM System Robust to Corner Cases

前言 最近看到一篇ICRA2024上的新文章&#xff0c;是关于多传感器融合SLAM的&#xff0c;好像使用了最近几年文章中较火的轮式里程计。感觉这篇文章成果不错&#xff0c;代码和数据集都是开源的&#xff0c;今天仔细读并且翻译一下&#xff0c;理解创新点、感悟研究方向、指导…

挑战杯 基于大数据的股票量化分析与股价预测系统

文章目录 0 前言1 课题背景2 实现效果3 设计原理QTChartsarma模型预测K-means聚类算法算法实现关键问题说明 4 部分核心代码5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于大数据的股票量化分析与股价预测系统 该项目较为新颖…

网络安全“三保一评”深度解析

“没有网络安全就没有国家安全”。近几年&#xff0c;我国法律法规陆续发布实施&#xff0c;为承载我国国计民生的重要网络信息系统的安全提供了法律保障&#xff0c;正在实施的“3保1评”为我国重要网络信息系统的安全构筑了四道防线。 什么是“3保1评”&#xff1f; 等保、分…

爬虫入门四(抽屉半自动点赞、xpath使用、动作链、打码平台、scrapy框架介绍与安装及创建项目)

文章目录 一、抽屉半自动点赞二、xpath的使用三、动作链四、打码平台介绍超级鹰打码基本测试 五、自动登录超级鹰六、scrapy框架介绍安装创建爬虫项目 一、抽屉半自动点赞 登录抽屉账号保存cookiesimport timeimport jsonfrom selenium import webdriverfrom selenium.webdrive…

基于YOLOv5+PySide6的火灾火情火焰检测系统设计深度学习

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;225火灾 获取完整源码源文件已标注的数据集&#xff08;1553张&#xff09;配置跑起来说明 可有偿49yuan一对一远程操作&#xff0c;在你电脑跑起来 效果展示&#xff1a; ​数据集在下载的文件夹&#xff1a;yolov5-5.0\…

一键生成PDF即刻呈现:轻松创建无忧体验

在信息爆炸的时代&#xff0c;我们每天都在与各种文件、资料打交道。无论是工作中的报告、合同&#xff0c;还是学习中的笔记、论文&#xff0c;如何高效、安全地管理这些珍贵的资料&#xff0c;成为了我们迫切的需求。幸运的是&#xff0c;随着科技的发展&#xff0c;我们不再…

PX4FMU和PX4IO最底层启动过程分析(下)

PX4FMU和PX4IO最底层启动过程分析&#xff08;下&#xff09; PX4FMU的系统启动函数为nash_main(int argc,char *argv[]) PX4IO的系统启动函数为nash_start(int argc,char *argv[]) PX4FMU启动函数nash_main(int argc,char *argv[]) 首先分析一下nash_main(int argc,char *a…

五大方法教你如何分分钟构造百万测试数据!

在测试的工作过程中&#xff0c;很多场景是需要构造一些数据在项目里的&#xff0c;方便测试工作的进行&#xff0c;构造的方法有很多&#xff0c;难度和技术深度也不一样。本文提供方法供你选择。 在测试的工作过程中&#xff0c;很多场景是需要构造一些数据在项目里的&#…

【《高性能 MySQL》摘录】第 2 章 MySQL 基准测试

文章目录 2.1 为什么需要基准测试2.2 基准测试的策略2.2.1 测试何种指标 2.3 基准测试方法2.3.1 设计和规划基准测试2.3.2 基准测试应该运行多长时间2.3.3 获取系统性能和状态2.3.4 获得准确的测试结果2.3.5 运行基准测试并分析结果2.3.6 绘图的重要性 2.4 基准测试工具…

vue3 实现 el-pagination页面分页组件的封装以及调用

示例图 一、组件代码 <template><el-config-provider :locale"zhCn"><el-pagination background class"lj-paging" layout"prev, pager, next, jumper" :pager-count"5" :total"total":current-page"p…

深入浅出JVM(十)之字节码指令(下篇)

上篇文章深入浅出JVM&#xff08;九&#xff09;之字节码指令&#xff08;上篇&#xff09;已经深入浅出说明加载存储、算术、类型转换的字节码指令&#xff0c;本篇文章作为字节码的指令的下篇&#xff0c;深入浅出的解析各种类型字节码指令&#xff0c;如&#xff1a;方法调用…

计算机网络:思科实验【2-MAC地址、IP地址、ARP协议及总线型以太网的特性】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;Cisco Packet Tracer实验 本文对应的实验报告源文件请关注微信公众号程序员刘同学&#xff0c;回复思科获取下载链接。 实验目的实验环境实验内容MAC地址、IP地址、ARP协议总线型以太网的…

2024-02-25 Unity 编辑器开发之编辑器拓展7 —— Inspector 窗口拓展

文章目录 1 SerializedObject 和 SerializedProperty2 自定义显示步骤3 数组、List 自定义显示3.1 基础方式3.2 自定义方式 4 自定义属性自定义显示4.1 基础方式4.2 自定义方式 5 字典自定义显示5.1 SerizlizeField5.2 ISerializationCallbackReceiver5.3 代码示例 1 Serialize…

音频smmu问题之smmu学习

一、音频smmu 内存访问问题 在工作中&#xff0c;遇到一个smmu问题&#xff0c;主要log信息如下&#xff1a; arm-smmu 15000000.apps-smmu: Unhandled arm-smmu context fault from soc:spf_core_platform:qcom,msm-audio-ion! arm-smmu 15000000.apps-smmu: FAR 0x0000000…

【考研数学】基础阶段习题1800和660怎么选❓

我建议以1800题为主 1800题包含基础和强化两部分&#xff0c;基础部分题量很大&#xff0c;类型也很全面&#xff0c;并且难度一点也不高&#xff0c;适合基础不好的学生来做。 660题难度比较大&#xff0c;不适合基础阶段做。 660题虽然名字叫基础训练&#xff0c;但是不适…