结构体介绍(2)

ops/2024/9/23 4:36:27/

结构体介绍(2)

  • 前言
  • 一、结构体的内存对齐之深入理解
    • 为什么存在内存对齐?
    • 修改默认对齐数
  • 二、结构体传参
    • 2.1:该怎么传参呢?
  • 三、结构体实现位段
    • 3.1什么是位段
    • 位段的内存分配
    • 位段的跨平台问题
  • 总结


前言

根据之前讲了结构体的《声明》、《创建》、《初始化》、《结构体内存对齐》。 接下来我们就来深入探讨结构体


问题:那么有没有考虑结构体嵌套结构体的内存对齐呢?

一、结构体的内存对齐之深入理解

示例:

struct S3
{double d;char c;int i;
};
struct S4
{char c1;struct S3 s3;double d;
};
int mian()
{struct S4 s4 = { 0 };printf("%zd\n", sizeof(s4));return 0;
}

根据规则4:如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员最大对齐数的整数辈出,结构体的整体大小就是所有最大对齐数(包含嵌套结构体中成员对齐数)的整数倍。
那么根据以上代码:
s3就对应其中成员最大对齐数为double类型(8)
再根据规则1、2、3就可以得出这个结构体的大小
在这里插入图片描述

为什么存在内存对齐?

在这里插入图片描述

修改默认对齐数

#pragma 这个预处理指令,可以改变编译器的默认对齐数。

#pragma pack(1)//把默认对齐数定义为1
struct S
{char c;int i;char a;
};
int main()
{printf("%zd\n", sizeof(struct S));return 0;
}

在这里插入图片描述

二、结构体传参

2.1:该怎么传参呢?

代码如下(示例):

struct S
{int arr[1000];int n;double b;
};
void print1(struct S tmp)
{int i = 0;for (i = 0;i < 5;i++){printf("%d", tmp.arr[i]);}printf("%d\n", tmp.n);printf("%lf\n", tmp.b);
}
int main()
{struct S s = { {1,2,3,4,5},100,3.14 };print1(s);//这里s里面的数组arr[1000](空间大),但是传参过去时会有空间的浪费return 0;
}

这里s里面的数组arr1000,但是传参过去时会有空间的浪费,那么我们用地址来传
同时我们也可以达到同样的效果

修正:
struct S
{
int arr[1000];
int n;
double b;
};
void print1(struct S* tmp)
{
int i = 0;
for (i = 0;i < 5;i++)
{
printf(“%d”, tmp->arr[i]);
}
printf(“%d\n”, tmp->n);
printf(“%lf\n”, tmp->b);
}
int main()
{
struct S s = { {1,2,3,4,5},100,3.14 };
print1(&s);
return 0;
}
在这里插入图片描述

三、结构体实现位段

3.1什么是位段

在这里插入图片描述
比如:
struct S
{
int_a:2;//位段结构、4个字节----32个bit
int_b:5;//位段结构、4个字节----32个bit
int_c:10;//位段结构、4个字节----32个bit
int_d:30;//位段结构、4个字节----32个bit
};
int main()
{
return 0;
}

首先: 位段中的位是二进制位
那么0就可以用2个bit来表达00
1-----------2---------------01
2-----------2---------------10
3…以此类推
在这里插入图片描述
这样可以节省很多空间
在这里插入图片描述
节省内存
那么位段是怎么分配内存的呢?

位段的内存分配

3.2

在这里插入图片描述
根据以下图片分析:
在这里插入图片描述
每次申请1个字节(8个bit位)这里采用了从右向左,浪费操作。
在这里插入图片描述
在这里插入图片描述
按照16进制来表达时:0x620304。
浪费的bit用0来填补
在这里插入图片描述
例子:在这里插入图片描述
根据上面的图片可知:
当不够你所要申请的空间,那么就会重新开辟一个空间来容纳你的空间
(如:第一个a申请了2个bit,第二个申请了5个bit,第三个申请10个bit,而第四个要30个bit,那就在申请一个空间来容纳第四个空间!

位段的跨平台问题

在这里插入图片描述
在16位int是2个字节!!!
如果我们把16位看成32位那么这样就会产生不同结果!!!
所以位段是不跨平台的。


总结

1:结构体内存对齐----浪费空间来促进时间;
2:位段-------节省内存;
3:跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在


http://www.ppmy.cn/ops/33798.html

相关文章

【八股】AQS,ReentrantLock实现原理

AQS 概念 AQS 的全称是 AbstractQueuedSynchronized &#xff08;抽象队列同步器&#xff09;&#xff0c;在java.util.concurrent.locks包下面。 AQS是一个抽象类&#xff0c;主要用来构建锁和同步器&#xff0c;比如ReentrantLock, Semaphore, CountDownLatch&#xff0c;里…

使用python和pyqt开发的抽签小程序v1.0

使用python和pyqt开发的抽签小程序v1.0 作用效果代码 作用 对输入框中的文本进行随机抽取&#xff0c;抽取数量为3行。 效果 代码 import sys import random from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QTextEdit, QPushButton, QMessageBoxclass Ra…

Android Studio学习笔记——数据库存储

Android Studio学习笔记——数据库存储 6.1持久化技术简介6.2 文件存储将数据存储到文件中从文件中读取数据 6.3 SharedPreferences存储6.3.1 将数据存储到是SharedPreferences中6.3.2 从SharedPreferences中读取数据6.3.3 实现记住密码功能 6.4 SQLite数据库存储6.4.1 创建数据…

急速入门Prompt开发之跨国婚姻小助手

文章目录 前言MoonShot编写提示词对接模型WebUI编写完整代码 前言 整个活&#xff0c;同时分享技术~至于是啥活&#xff0c;懂得都懂&#xff0c;男孩子自强自尊自爱&#xff01;&#xff01;&#xff01; 先看看实现效果吧&#xff1a; 那么这里的话&#xff0c;我们使用到的…

Linux内核深入学习 - 内核同步

目录 内核抢占 同步原语 per-CPU变量 API Per CPU 变量的应用 per CPU 变量在多文件下的用法 原子操作 API 优化和内存屏障 自旋锁 自旋锁 API 函数 读写锁 API RCU 信号量 API 1. 信号量的结构&#xff1a; 2. 初始化函数sema_init 3. 可中断获取信号量函数…

学习mysql相关知识记录

执行一条select语句&#xff0c;期间发生了什么&#xff1f; MySQL的执行流程&#xff1a; 连接器 TCP连接 查询缓存 很鸡肋被取消 解析SQL 解析器 语法分析词法分析 执行SQL 预处理器 检查是否存在将 select * 中的 * 符号&#xff0c;扩展为表上的所有列 优化器 优化器主要…

删除虚拟机存储策略中vSAN默认存储策略

登录vSphere Client&#xff0c;展开左上角设置-策略和配置文件-虚拟机存储策略&#xff0c;可以查看系统默认创建的虚拟机存储策略。这些存储策略由系统自动生成&#xff0c;其中有一部分存储策略仅用于vSAN数据存储&#xff0c;作为vSAN 默认存储策略以应用于&#xff0c;当在…

【iOS】KVO

文章目录 前言一、KVO使用1.基本使用2.context使用3.移除KVO通知的必要性4.KVO观察可变数组 二、代码调试探索1.KVO对属性观察2.中间类3.中间类的方法3.dealloc中移除观察者后&#xff0c;isa指向是谁&#xff0c;以及中间类是否会销毁&#xff1f;总结 三、KVO本质GNUStep窥探…