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://www.mzph.cn/news/701791.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8S—集群调度

目录 前言 一 List-Watch 1.1 list-watch概述 1.2 list-watch工作机制 二 集群调度 2.1 调度过程 2.2 Predicate 和 Priorities 的常见算法和优先级选项 2.3 调度方式 三 亲和性 3.1 节点亲和性 3.2 Pod 亲和性 3.3 键值运算关系 3.4 Pod亲和性与反亲和性 3.5 示例…

音视频数字化(数字与模拟-电影)

针对电视屏幕,电影被称为“大荧幕”,也是娱乐行业的顶尖产业。作为一项综合艺术,从被发明至今,近200年的发展史中,无人可以替代,并始终走在时代的前列。 电影回放的原理就是“视觉残留”,也就是快速移过眼前的画面,会在人的大脑中残留短暂的时间,随着画面不断地移过,…

暑期宅家?计算机专业必看的8部电影!一定要安利给你们!

代码编程看上去枯燥乏味&#xff0c;但也是艺术的&#xff0c;感性的&#xff0c;计算机编程的许多概念被应用于电影中&#xff0c;其中有些非常之酷炫&#xff0c;它们甚至能帮助开发人员理解一些编程概念。 所以今天学姐来给大家推荐几部心中top级的编程人必看电影&#xff0…

nginx(二)

nginx的验证模块 输入用户名和密码 第一步先下载httpd 这个安装包 第二步编辑子配置文件 然后去网页访问192.168.68.3/admin/ 连接之后&#xff0c;会出现404&#xff0c;404出现是因为没给网页写页面 如果要写页面&#xff0c;则在/opt/html&#xff0c;建立一个admin&#x…

max_element和min_element使用

头文件 #include<alorithm> 作用 用于返回数组或容器中最值元素(最小值、最大值)&#xff0c;值和下标。 使用举例 #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() {/*数组初始化*/vector<int>…

软件设计师软考题目解析05 --每日五题

想说的话&#xff1a;要准备软考了。0.0&#xff0c;其实我是不想考的&#xff0c;但是吧&#xff0c;由于本人已经学完所有知识了&#xff0c;只是被学校的课程给锁在那里了&#xff0c;不然早找工作去了。寻思着反正也无聊&#xff0c;就考个证玩玩。 本人github地址&#xf…

MySQL--索引结构

索引-索引结构 1. 概述2. 二叉树3. B-Tree4. BTree5. Hash 1. 概述 MySQL的索引是在存储引擎层实现的&#xff0c;不同的存储引擎有不同的索引结构&#xff0c;主要包含以下几种&#xff1a; 上述是MySQL中所支持的所有的索引结构&#xff0c;下面展示不同的存储引擎对于索引…

JDK下载安装

资源展示 安装说明 傻瓜式安装&#xff0c;下一步即可。建议&#xff1a;安装路径不要有中文或者空格等特殊符号。本套课程会同时安装JDK8 和 JDK17&#xff0c;并以JDK17为默认版本进行讲解。 安装步骤 &#xff08;1&#xff09;双击jdk-17_windows-x64_bin.exe文件&#…

8-pytorch-损失函数与反向传播

b站小土堆pytorch教程学习笔记 根据loss更新模型参数 1.计算实际输出与目标之间的差距 2.为我们更新输出提供一定的依据&#xff08;反向传播&#xff09; 1 MSEloss import torch from torch.nn import L1Loss from torch import nninputstorch.tensor([1,2,3],dtypetorch.fl…

(只需三步)免费使用知网的攻略

通过浙江图书馆可以进入知网&#xff0c;并且查看与下载都是免费的。 &#xff08;只需要三步&#xff0c;很简单的。&#xff09; 第一步&#xff1a;注册浙江图书馆账号 打开zfb&#xff0c;搜索“浙江图书馆”小程序&#xff0c;进入个人中心->办理读者证&#xff0c;…

不同尺度下的网络控制方式

《三国演义》和《长安十二时辰》有什么不同&#xff1f; 关羽败走麦城&#xff0c;远在千里之外的刘备收到两个信号&#xff0c;一个需要 “星夜驰援”&#xff0c;紧接着 “二弟休矣”&#xff0c;三国的故事在东亚大陆展开&#xff0c;地理尺度巨大&#xff0c;星夜不星夜其…

PHP语言检测用户输入密码及调用Python脚本

现在有一份计算流体力学N-S方程的Python脚本&#xff0c;想要在用户登录网站后可以可以运行该脚本&#xff0c;然后将脚本运行后绘制的图片显示在用户网页上。 建一个名为N_S.py的python脚本文件&#xff0c;这个脚本在生成图像后会自行关闭&#xff0c;随后将图片保存在指定的…

BIO实战、NIO编程与直接内存、零拷贝深入辨析

BIO实战、NIO编程与直接内存、零拷贝深入辨析 长连接、短连接 长连接 socket连接后不管是否使用都会保持连接状态多用于操作频繁&#xff0c;点对点的通讯&#xff0c;避免频繁socket创建造成资源浪费&#xff0c;比如TCP 短连接 socket连接后发送完数据后就断开早期的http服…

简单上手若依框架

简介 若依是一个基于SpringBoot&#xff0c;Shiro&#xff0c;Mybatis的权限后台管理系统官网文档&#xff1a;介绍 | RuoYi源码 前后端不分离 RuoYi: &#x1f389; 基于SpringBoot的权限管理系统 易读易懂、界面简洁美观。 核心技术采用Spring、MyBatis、Shiro没有任何其它重…

第6.4章:StarRocks查询加速——Colocation Join

目录 一、StarRocks数据划分 1.1 分区 1.2 分桶 二、Colocation Join实现原理 2.1 Colocate Join概述 2.2 Colocate Join实现原理 三、应用案例 注&#xff1a;本篇文章阐述的是StarRocks-3.2版本的Colocation Join 官网文章地址&#xff1a; Colocate Join | StarRoc…

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

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

Centos服务器部署前后端项目

目录 准备工作1. 准备传输软件2. 连接服务器 部署Mysql1.下载Mysql(Linux版本)2. 解压3. 修改配置4. 启动服务另一种方法Docker 部署后端1. 在项目根目录中创建Dockerfile文件写入2. 启动 部署前端1. 在项目根目录中创建Dockerfile文件写入2. 启动 准备工作 1. 准备传输软件 …

全网唯一基于共享内存的C++ RPC框架

首先声明&#xff1a;我不是标题党&#xff0c;我是在找遍全网&#xff0c;没有找到一个基于共享内存实现、开源且跨平台的C RPC框架之后&#xff0c;才着手开发的这个框架。 项目地址&#xff1a;https://github.com/winsoft666/veigar 1. Veigar Veigar一词来源于英雄联盟里…

2024年湖北省事业单位考试报名流程图解

⏰ 时间安排 ✔️ 注册&#xff1a;2024年2月19日至2月27日15:00 ✔️ 报名&#xff1a;2024年2月21日9:00至2月27日17:00 ✔️ 资格审查&#xff1a;2024年2月21日9:00至2月28日9:00 ✔️ 缴费确认&#xff1a;2024年2月28日9:00至3月1日24:00 ✔️ 岗位调整和改报&#…

上门服务系统|上门服务小程序|上门服务软件开发

随着移动互联网技术的普及&#xff0c;上门服务小程序系统成为现代企业数字化转型的关键一环。这一系统为消费者提供了更加便捷、高效以及个性化的服务体验&#xff0c;同时也为企业带来了更广阔的商业机会。让我们来看看上门服务小程序系统的优势和功能。 首先&#xff0c;上门…