你是真的“C”——结构体中鲜有人知的“秘密”

简介: 结构体,属于一种自定义的结构体类型。是对于我们内置数据类型的一个补充,它的应用是非常广的。想必大家在学校已经学习了对结构体有了一定的了解,你以为你已经掌握了。其实,你只是初识了一下结构体而已。你听说过结构体内存对齐吗?听说过位段吗?我相信大家都听说过游戏中的段位~ 如果没有,那就说明你还没有真真了解结构体。废话不多说,接下来我就围绕着着两个核心要点,和大家分享我对结构体的认知和了解。

微信图片_20230427214238.gif

😎博客昵称:博客小梦

😊最喜欢的座右铭:全神贯注的上吧!!!

😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘微信图片_20230427160707.gif


前言🙌



   哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!😘我仅已此文,和大家分享你是真的“C”——结构体中的精髓剖析【内存对齐】+ 【位段】。都是精华内容,可不要错过哟!!!😍😍😍


  结构体,属于一种自定义的结构体类型。是对于我们内置数据类型的一个补充,它的应用是非常广的。想必大家在学校已经学习了对结构体有了一定的了解,你以为你已经掌握了。其实,你只是初识了一下结构体而已。你听说过结构体内存对齐吗?听说过位段吗?我相信大家都听说过游戏中的段位~ 如果没有,那就说明你还没有真真了解结构体。废话不多说,接下来我就围绕着着两个核心要点,和大家分享我对结构体的认知和了解。


结构体内存对齐:😊


结构体内存对齐存在的意思是什么?😘

很多的参考资料是这样阐述的:


  • 1.平台原因(移植原因):
  • 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 2.性能原因:
  • 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
  • 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
  • 3.总的来说:结构体的内存对齐是拿空间来换取时间的做法。


我们知道,任何数据类型都有大小而言。那么结构体的大小是多少呢?4byte?8byte?… 其实,要计算结构体的大小,首先需要搞明白结构体中的内存对齐


既然,结构体内存对齐有那么大的价值,咋废话不多讲,我们直击主题:结构体内存对齐的几条核心法则:


1.标准规定:结构体的首成员存放在相对于起始地址的0偏移处。

2.接下来的成员依次放在其对应对齐数的整数倍偏移量处。对齐数 = 取 默认对齐数 和自身内存大小之中的较小者。

3.默认对齐数与环境有关,在vs环境下,默认对齐数是8,而在gcc环境下,没有默认对齐数。成员的自身大小就是对齐数。

4.当结构体的所有成员都放进内存中后,结构体的大小 = max(每成员的对齐数)的整数倍。即使不用那么多空间,也需要浪费空间来进行分配,进行内存对齐。

5.当结构体中嵌套一个结构体成员,结构体的大小还是按照取最大对齐数的整数倍,这里的对齐数是包含结构体中的对齐数的,在这些之中取出最大的那个。其余按照上述法则。


究竟是否像上述法则所说这样来进行内存对齐呢?接下来我通过几个例子来分析一波,帮助大家理解一下。


内存对齐例子详细剖析:😘


例题一: 😍

struct S1
{
 char c1;
 int i;
 char c2;
};


上述的结构体大小是多少呢?

咱们画图分析:

微信图片_20230428163531.png


所以答案应该是12 。是不是呢?我们在编译器中运行检验一下:

程序运行结果图:

微信图片_20230428163556.png


果然是12!!!。说明我们的法则是对的,刚才的画图分析也是正确哒~


例题二: 😍

struct S2
{
 char c1;
 char c2;
 int i;
};


咱们画图分析:

微信图片_20230428163648.png

程序运行结果:

微信图片_20230428163651.png


发现一个问题:结构体S1和S2的成员都是一样的,只是放的位置不同而已,但是S1分配的空间却比S2要多,这显然是浪费更多的空间了。


结论:那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:让占用空间小的成员尽量集中在一起。


结构体中的位段:😊


什么是位段?😘


相比大家对于游戏段位还是很了解的😊,但位段和段位可不一样哦~ 位段属于一种自定义的数据类型。位段的声明和结构体是类似的,有两个不同:


  • 1.位段的成员必须是 int、unsigned int 或signed int(整形家族都行,只是int 用到的频率比较高) 。
  • 2.位段的成员名后边有一个冒号和一个数字。后面的数字表示的是bit。

举个栗子,让大家感受一下位段的魅力! 😍

struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};


那位段A的大小是多少?


程序运行结果:

微信图片_20230428163904.png


大家看到,如果没有位段的话,这个结构体的大小肯定大于8个字节的。位段的作用起到节省空间的作用。


位段的内存分配😘

1.位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

2.位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。


举个栗子: 😍

空间是如何开辟的?

struct S
{
  char a : 3;
  char b : 4;
  char c : 5;
  char d : 4;
};
int main()
{
  struct S s = { 0 };
  s.a = 10;
  s.b = 12;
  s.c = 3;
  s.d = 4;
}


画图分析:

微信图片_20230428164040.png

程序运行结果:

微信图片_20230428164047.png


2.3 位段的跨平台问题😘


  • 1.int 位段被当成有符号数还是无符号数是不确定的。
  • 2.位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。
  • 3.位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
  • 4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。


总结:跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。


2.4 位段的应用😘


在网路协议中用处很广,例如如下图所示:

微信图片_20230428164241.png


这里的数字表示的都是bit,其实就是运用了位段的知识。

网络中就像下图所示,数据是在网络中传输的。如果太大,就会造成网络堵塞,影响效率。网络中的数据是十分庞大的,因此,位段的价值就体现出来啦!


微信图片_20230428164243.png


总结撒花💞


   本篇文章旨在分享结构体中鲜有人知的“秘密”。希望大家通过阅读此文有所收获!😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

相关文章
|
安全 API 网络架构
9-6|我现在请求一个接口,怎么关闭认证啊
9-6|我现在请求一个接口,怎么关闭认证啊
|
负载均衡 Java 应用服务中间件
程序员的nginx技能包(1)——nginx是啥,对程序员有啥用
nginx是啥 nginx就是个服务器,做Java Web的童鞋可能比较了解Tomcat、做dotNet Web的童鞋可能比较了解IIS、还有非常出名的apache服务器等等等等。
146 0
|
10天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
9天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
417 130
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
3天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
199 138
|
9天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
381 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
3天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
199 136
|
21天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1356 8