结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)下

简介: 结构体全解,适合初学者的一条龙深度讲解(附手绘图详解)

2.1修改默认对齐数


我们可以通过#pragma pack()指令来修改默认对齐数。


#include <stdio.h>
#pragma pack(1)
//设置默认对齐数为1
struct S1
{
  char c1;
  int i;
  char c2;
};
int main()
{
  //输出的结果是什么?
  printf("%d\n", sizeof(struct S1));
  return 0;
}


968045478fc11a763247b86708e8801d_01ec18b9e3da48b8a60163a9b0185089.png


可以看到,答案不再是12,默认对齐数确实被修改了。


想要取消的话就引入一个空指令。


#include <stdio.h>
#pragma pack(1)//设置默认对齐数为1
#pragma pack()//取消设置的默认对齐数,还原为默认
struct S1
{
  char c1;
  int i;
  char c2;
};
int main()
{
  //输出的结果是什么?
  printf("%d\n", sizeof(struct S1));
  return 0;
}


a4973c80bc93d1b85c6291017aca52bb_dcdae90c9721485bba16108f55ea6530.png


2.2 结构体传参


下面print1和print2那个比较好?


struct S
{
 int data[1000];
 int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
 printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
 printf("%d\n", ps->num);
}
int main()
{
 print1(s);  //传结构体
 print2(&s); //传地址
 return 0;
}

上面的 print1 和 print2 函数哪个好些?

答案是:首选print2函数。

原因:

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

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

所以结构体传参数时,要传结构体的地址。


3.1位段


结构体讲完就得讲讲结构体实现 位段 的能力。

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

A就是一个位段的类型,位段可以控制所给的空间大小,达到节省空间的目的。


它所占空间是多大?


#include <stdio.h>
struct A
{
  int _a : 2;
  int _b : 5;
  int _c : 10;
  int _d : 30;
};
int main()
{
  printf("%d\n", sizeof(struct A));
  return 0;
}


e567e08aa3df4cd5a68b1cfeb9cd141b_144a3809ce294084ad85275b813a0dd4.png


它占了8*8=64个比特位。


从16个字节优化到8个字节,位段的功能可以说是十分强大。


3.2 位段的内存分配


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

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

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

#include <stdio.h>
//一个例子
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;
//空间是如何开辟的?
return 0;
}


首先做一个假设,假设内存中的比特位是由右向左使用的。

一个字节内部,剩余的比特位不够使用时,直接浪费掉。


14da58387aaba67e5f185188dfd193ba_8b4225b5319f474b8412cefbff62afa3.png


我们猜想是这个样子。


转换成16进制为:


62  03  04


我们来调试看看:


2f717c4b63d0f72f57b1bfa54d44a952_362b666259d04c64be1e470baf7d2359.png


我们的猜想是正确的!


3.3 位段的跨平台问题


1. int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定。( 16 位机器最大 16 , 32 位机器最大 32 ,写成 27 ,在 16 位机

器会出问题。

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是

舍弃剩余的位还是利用,这是不确定的。

总结:

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


5afd1174262572c8492490f4c580e7b1_304e31657dd24eee9c48b710a07b8d3e.png


这篇博客旨在总结我自己阶段性的学习,要是能帮助到大家,那可真是三生有幸!😀如果觉得我写的不错的话还请点个赞和关注哦~我会持续输出编程的知识的!🌞🌞🌞  


相关文章
|
9天前
|
机器人 API 调度
基于 DMS Dify+Notebook+Airflow 实现 Agent 的一站式开发
本文提出“DMS Dify + Notebook + Airflow”三位一体架构,解决 Dify 在代码执行与定时调度上的局限。通过 Notebook 扩展 Python 环境,Airflow实现任务调度,构建可扩展、可运维的企业级智能 Agent 系统,提升大模型应用的工程化能力。
|
人工智能 前端开发 API
前端接入通义千问(Qwen)API:5 分钟实现你的 AI 问答助手
本文介绍如何在5分钟内通过前端接入通义千问(Qwen)API,快速打造一个AI问答助手。涵盖API配置、界面设计、流式响应、历史管理、错误重试等核心功能,并提供安全与性能优化建议,助你轻松集成智能对话能力到前端应用中。
706 154
|
15天前
|
人工智能 数据可视化 Java
Spring AI Alibaba、Dify、LangGraph 与 LangChain 综合对比分析报告
本报告对比Spring AI Alibaba、Dify、LangGraph与LangChain四大AI开发框架,涵盖架构、性能、生态及适用场景。数据截至2025年10月,基于公开资料分析,实际发展可能随技术演进调整。
963 152
|
负载均衡 Java 微服务
OpenFeign:让微服务调用像本地方法一样简单
OpenFeign是Spring Cloud中声明式微服务调用组件,通过接口注解简化远程调用,支持负载均衡、服务发现、熔断降级、自定义拦截器与编解码,提升微服务间通信开发效率与系统稳定性。
362 156
|
7天前
|
分布式计算 监控 API
DMS Airflow:企业级数据工作流编排平台的专业实践
DMS Airflow 是基于 Apache Airflow 构建的企业级数据工作流编排平台,通过深度集成阿里云 DMS(Data Management Service)系统的各项能力,为数据团队提供了强大的工作流调度、监控和管理能力。本文将从 Airflow 的高级编排能力、DMS 集成的特殊能力,以及 DMS Airflow 的使用示例三个方面,全面介绍 DMS Airflow 的技术架构与实践应用。
|
8天前
|
人工智能 自然语言处理 前端开发
Qoder全栈开发实战指南:开启AI驱动的下一代编程范式
Qoder是阿里巴巴于2025年发布的AI编程平台,首创“智能代理式编程”,支持自然语言驱动的全栈开发。通过仓库级理解、多智能体协同与云端沙箱执行,实现从需求到上线的端到端自动化,大幅提升研发效率,重塑程序员角色,引领AI原生开发新范式。
502 2