结构体的内存对齐

2023-05-16

之前我们都知道int类型大小是4个字节,char类型为1个字节,double为8个字节等等。

但是结构体是由很多类型组成的,那么它的大小是多少呢?是所有类型相加之和还是另有算法?

接下俩我们将仔细的探讨它.


  先来说结论:结构体大小不是所有类型大小的和,而是存在一种内存对齐的方式,使得结构体中类型按某种方式对齐。


具体是怎么样的对齐方式呢?

我们先来看以下代码:

struct S1
{
char c1;
int i;
char c2;
};
printf("%d\n", sizeof(struct S1));

大小不是1+4+1=6个字节哦。我们先看结果:

结果是12.是不是很不符合常理呢.

接下俩废话不多说,直接上内存对齐规则,然后我再一一解析它:


1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到
某个数字(对齐数)的整数倍的地址处。
 
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
   VS中默认的值为8
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。


我们先一句话一句话来分析.

一.第一个成员在与结构体变量偏移量为0的地址处。

  偏移量可以抽象的理解为在内存中的位置。后面在讲解中慢慢会理解的.非常容易

例如上面那个例子:

第一个成员是 char c1;

那么位于偏移量为0的地址处,这样画一下会更容易理解.

 其中 0 - 16数字都是偏移量,数字2代表偏移量为2,16则代表偏移量为16.

  那么按照第一条规则:第一个成员应该在偏移量为0的位置,我们放入其中:

就成了上图所示.看接下来一条规则:

2. 其他成员变量要对齐到某个数字(对齐数)的最小整数倍的地址处。
 
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
   VS中默认的值为8

要对齐到对齐数的整数倍。首先看对齐数是编译器默认的和该结构体成员的较小值.

 vs编译默认的是8,而我们下一个类型即第二个类型为int类型,大小为4个字节.

所以我们取较小的值,即4,所以对齐数是4.

要对其到4的整数倍,我们此时只能取4的1倍了,如果是0,则4的0倍也是0,而偏移量为0的地方已经被占用,所以只能取4的1倍,即在偏移量为4的地方,开始占用一个int字节大小,空出来的空间,如偏移量为1,2,3的地方被浪费掉,不用再理.如下图:

 

接下来,第三个成员是char c2 : 

同样的办法,

vs编译默认的是8,而我们这个类型即char类型,大小为1个字节.

所以我们取较小的值,即1,所以对齐数是1.

然后对齐到1的最小倍数,既然是1的倍数,那肯定是多少都可以了,1,2,3,4都可,但是我们偏移量此时已经到了7的位置,所以下一个只能占用偏移量为8的位置,即8的倍数.

如下:

 此时所有成员已经对其完毕,接着看第三条规则:

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

此时的最大对齐数为结构体成员中占用空间最大的。

结构体成员类型分别为:char、int、char

最大的类型是int,即4个字节,即最大对齐数为4个字节..

 所以结构体的总大小为4的整数倍,注意此时已经占用了9个字节,不是8个字节!

因为偏移量包括0,所以此时只是偏移量为8,但已经占用了9个字节。

所以此时只能是4的3倍数,即12个字节。若是4的2的倍数,则是8,小于我们已经占用的字节了,所以8肯定不行。

所以综上,此结构体的大小为12个字节.

这样的懂了,那下面这样的代码该如何处置呢?

struct S4
{
char c1;
struct S1 s1;
double d;
};
printf("%d\n", sizeof(struct S4));

注:s1是上面例子的是s1

我们在S4结构体里嵌套了一个S1结构体变量s1,那这样我们该如何计算呢?

首先按照第一条规则,将c1放在偏移量为0的位置.

下面重点来了,下一个成员是一个结构体的变量,此时它便不再遵循第2条规则,直接看第4条规则: 

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

正常来说,我们将此成员的大小和编译器默认的大小作比较取最小值,然后找它的最小整倍数对齐。但是如果成员是一个结构体,它便不在按照自身的大小来计算,而是按照他自己的最大对齐数. 我们上面已经知道S1的最大对齐数是4,所以是4的倍数,此时只能从4的位置开始,即4的1倍数,如下:

 

接下来第三个成员是double类型,大小为8个字节,和编译器默认相同。那就取8,此时只能取8的2倍,即偏移量为16的位置.如下:

接着总大小为所有成员(包括嵌套的那个结构体)的最大对齐数的整数倍

他们的对齐数分别为1 4 8

所以最大对齐数是8,然后整数倍,只能是24,即8的3倍. 

即此结构体的大小为24.我们看结果:

结果正确.

这里还有几道题,希望有时间可以做一下来巩固一下自己所学的知识。 

 

//求S2结构体的大小
struct S2
{
char c1;
char c2;
int i;
};

//求S3结构体的大小
struct S3
{
double d;
char c;
int i;
};

结果自己可以运行尝试一下哦,看看与自己运算的是否相符。

如有疑问的地方,欢迎私信联系哦.

题外话:

为什么存在内存对齐?
大部分的参考资料都是如是说的:
1. 平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特
定类型的数据,否则抛出硬件异常

2. 性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访

结构体的内存对齐是拿空间来换取时间的做法.

---来源于比特就业课教材

那么结构体的内存对齐就到此为止了,还是一样,若是有疑问的地方,欢迎留言或者私信哦。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

结构体的内存对齐 的相关文章

  • 一款Java开源的Springboot即时通讯 IM,附源码

    开篇 电商平台最不能缺的就是即时通讯 xff0c 例如通知类下发 xff0c 客服聊天等 今天 xff0c 就来给大家分享一个开源的即时通讯系统 如对文章不感兴趣可直接跳至文章末尾 xff0c 有获取源码链接的方法 但文章内容是需要你简单的
  • dpkg 命令使用说明

    dpkg是一个debian包管理工具 能够对包进行安装 卸载 获取信息等操作 用法 xff1a 安装 xff08 解包并配置 xff09 xff1a dpkg i package file dpkg install package file
  • ubantu开启FTP使用 FileZilla与windows文件互传(图文教程)

    平台 xff1a VMware Workstation 16 Pro iso镜像 xff1a ubuntu 22 04 1 desktop amd64 iso 第一步 xff1a 先打开终端 第二步 xff1a 分别输入下面两条代码 xff
  • 虚拟机Ubuntu20.04安装NVIDIA显卡驱动失败原因

    本来想在ubuntu里使用Tensorflow的GPU版 但是按照一系列操作 xff0c 在处理显卡驱动问题的时候 xff0c 出现下图报错 xff1a 后来查到虚拟机不支持显卡驱动 xff0c 显卡不支持虚拟化 xff0c 所以不能用Te
  • C语言练习:输入一个十进制将其转换成八进制和十六进制

    文章目录 前言一 题意二 代码1 代码的实现2 读入数据 总结 前言 输入一个十进制将其转换成八进制和十六进制本题是在C语言中较为常见的问题 xff01 一 题意 在C环境中输入一个十进制数 xff0c 在结果中第一行输出8进制数第二行输出
  • 本第包含与远程包含--学习篇

    1 什么是文件包含 用一句话来说就是 xff0c 文件包含不是漏洞 xff0c 但是由于对包含进行的文件不可控 xff0c 导致了文件包含漏洞的产生 文件包含分为两种 1 本地文件包含LFI xff08 包含本地文件操控LFI xff09
  • Ubuntu20.04安装Java JDK

    1 官网下载 https www oracle com java technologies downloads java8 根据自己系统配置信息下载对应安装包 xff0c 常见的的Linux系统 xff0c Ubuntu下载后缀为 tar
  • Ubuntu获取文件路径

    1 可视化界面查看 xff08 ctrl 43 L xff09 可视化界面查看ubuntu默认的快捷键是ctrl 43 L xff0c 直接按下快捷键 xff0c 如图路径显示出来了 2 直接在终端输入pwd
  • 关于跨平台 UI 的思考

    一 xff1a 跨平台 xff0c 这里的跨平台 xff0c 指的是 xff1a Windows Linux MacOS IOS Andriod 二 xff1a 跨平台 xff0c 首先大家想到的是 Java 虽然众多平台都支持 Java
  • Ubuntu20.04安装IntelliJ IDEA2022步骤

    1 下载linux版本的idea 链接地址 xff1a IntelliJ IDEA The Capable amp Ergonomic Java IDE by JetBrains 2 解压到自己的路径下 在 usr local 路径下新建安
  • Debian 11 搭建fabric版本1.4的环境

    建议以下所有过程皆在root权限下进行 xff0c 否则在sudo权限切换的过程中会出现很多环境变量的问题 1 搭建Fabric的前置条件 1 1安装GOLANG Debian 11 安装部署 Go 和设置环境变量 1 2安装Docker
  • 如何用脚本自动生成httpd容器

    要用脚本自动生成httpd容器 xff0c 首先需要安装Docker 然后 xff0c 你可以编写一个简单的脚本来创建httpd容器 以下是一个示例脚本 xff1a bin bash 定义变量 name 61 34 my httpd 34
  • 如何用脚本自动生成多个httpd容器

    使用 96 crontab 96 来定时执行脚本 96 crontab 96 是一种在Unix和类Unix系统上自动定时执行命令或脚本的程序 你可以编辑你的 96 crontab 96 文件 xff0c 然后在该文件中添加定时执行脚本的条目
  • Microsoft Visual C++ 14.0 or greater is required的解决方法

    用pip去安装Python第三方库的时候 xff0c 安装不成功 xff0c 遇到问题 xff0c 提示有 error Microsoft Visual C 43 43 14 0 or greater is required Get it
  • ansible安装部署以及常用模块解析使用

    ansible安装部署 1 配置阿里云的eple源 我们使用yum命令安装ansible xff0c 需要阿里云的eple源 阿里云eple源下载地址 也可以通过下面命令获取 epel RHEL 8 centos8版本按照如下配置 1 xf
  • 使用rancher的rke2部署高可用的k8s集群

    目录 1 linux环境初始化及内核调优 xff08 1 xff09 设置主机名 关闭防火墙 配置集群ip映射 关闭selinux xff08 2 xff09 禁用linux的透明大页 标准大页 xff08 3 xff09 禁用swap分区
  • SPI总线

    1 spi总线简介 xff1a SPI xff08 Serial Peripheral Interface xff09 是串行外设接口的缩写 xff0c SPl是一种高速的 全双工 同步的串行通信总线 xff1b SPl采用主从 方式工作
  • 【C语言】链表——圈中游戏问题(数到3退出)

    问题描述 xff1a 有n个人围成一圈 xff0c 从第1个人开始报数1 2 3 xff0c 每报到3的人退出圈子 使用链表找出最后留下的人 分析 xff1a 1 用动态链表 2 链表中每个结点的数据域按顺序赋值1 2 3 xff0c 用指
  • MySQL数据库JSON数组拆分

    用SQL将 34 name 34 34 25岁及以下 34 34 value 34 1 34 name 34 34 36 40岁 34 34 value 34 2 34 name 34 34 31 35岁 34 34 value 34 3
  • python中类的定义、实例化、封装以及私有变量/方法

    1 定义类 python中定义一个类的格式如下 xff1a class MyClass object def init self data1 data2 self data1 61 data1 self data2 61 data2 def

随机推荐

  • 代码规范之Alibaba Java Coding Guidelines

    一 Alibaba Java Coding Guidelines 1 整体介绍 xff1a Alibaba Java Coding Guidelines 专注于Java代码规范 xff0c 目的是让开发者更加方便 快速规范代码格式 该插件在
  • 虚拟机上的备份与还原(有图)

    一 虚拟机上的C盘备份到D盘 xff08 1 xff09 将事先做好pe的u盘插入真机 xff0c 在弹出的对话框上选择连接到虚拟机上 如图1 1 xff08 2 xff09 登陆上虚拟机的win10重启 xff0c 在开始重新启动同时按下
  • vscode中使用C++实现mysql数据库编程(附带相关案例)

    windows下vscode连接Linux中的MySQL教程见 xff1a https blog csdn net weixin 47156401 article details 129469835 spm 61 1001 2014 300
  • 二进制移动

    二进制移动 1 算术左移 逻辑左移 算 术左移和逻辑左移一样都是右边补0 xff1a 比如 xff1a 00101011 算术左移一位 01010110 逻辑左移一位 01010110 对于二进制的数值来说左移n位等于原来的数值乘以2的n次
  • VMware虚拟机ubuntu等系统的安装(含镜像下载链接)

    本文将讲述VMware虚拟机ubuntu等系统的安装 xff0c 超详细的教程 xff0c 每一个步骤都会配图片 同时为了方便大家找到这些镜像 xff0c 直接把镜像直接放到百度网盘中 xff0c 供大家下载使用 由于博主个人原因 xff0
  • 全球首发,国产开源「文本-视频生成」模型!免费在线体验,一键实现视频生成自由...

    来源 xff1a 新智元 去年4月 xff0c OpenAI发布的DALL E 2用更高的分辨率 更真实的图像生成以及更准确地理解自然描述 xff0c 横扫整个AIGC领域 不过图像生成真正进入全民化还要数Stable Diffusion的
  • 1、回文判断(java数据结构)

    回文判断 回文是指正读反读均相同的字符序列 xff0c 如 abba 和 abdba 均是回文 xff0c 但 good 不是回文 编写一个程序 xff0c 使用栈判定给定的字符序列是否为回文 输入格式 输入待判断的字符序列 xff0c 按
  • 12、栈、队列和字符串的基本操作(Java数据结构)

    栈 队列和字符串的基本操作 使用栈与队列逐个处理字符串中的每个字符 将输入的字符串的字符依次入栈 xff0c 然后输出栈中元素个数与栈顶元素 xff0c 以空格分隔 然后将栈中元素依次出栈并输出 xff0c 出栈时将不等于指定字符的元素依次
  • 在虚拟机上使用Ghost备份/恢复操作系统

    课堂作业 xff1a Windows10备份与恢复 实验目的 xff1a 使用Ghost备份 恢复操作系统 需求描述 用Ghost软件为Windows 10样机制作备份镜像 将制作的Gho文件备份到本机其他磁盘 xff0c 以备不时之需 环
  • 如何利用抓包验证 三次握手,四次挥手

    三次握手 xff0c 四次挥手 1 打开Centos 7 6 虚拟机设置 xff0c 自定义网卡VMnet8 2 打开控制面板 网络和internet 网络连接 xff0c 查看VMnet8网卡IPV4地址 3 开启虚拟机 xff0c 点击
  • VMware、linux虚拟机设置网络实现虚拟机与主机网络互通

    需要配置三个方面才可以 xff0c 即 xff1a WMware网络配置 windows主机网络配置 虚拟机网络配置 首先 xff0c 确认VMware虚拟机设置中配置的网络连接方式为 xff1a NAT模式 可以在VMware上方的菜单中
  • 单臂路由的使用及详细配置命令

    实验环境 xff1a 需求描述 xff1a 使各个vlan之间都能ping通 操作步骤 xff1a 1 LSW1划分vlan xff0c 讲对应的端口划分到对应的vlan 里面 xff0c 进入g0 0 1 xff0c 端口设置为trunk
  • 学习华为特殊端口模式Hybrid(带配置命令)

    目录 HybridHybrid接口工作原理实验环境 xff1a 实验步骤 xff1a 一 交换机的配置1 SW1的配置2 SW2的配置 二 PC地址配置三 PC互ping xff0c 简述PC互ping流程 Hybrid Hybrid接口工
  • ENSP 单臂路由的配置(带配置命令)

    目录 单臂路由原理实验环境 xff1a 需求描述 xff1a 操作步骤 xff1a 一 LSW1的配置二 R1的配置三 配置PC IP地址四 验证 单臂路由原理 在路由器的一个接口上通过配置逻辑接口的方式和E trunk多链路汇聚 xff0
  • Samba服务的匿名访问用户访问以及权限控制

    目录 一 samba服务概述二 Samba服务的配置2 1 安装DHCP服务2 2 win10通过DHCP 获取地址2 3 安装并配置Samba服务2 3 1 修改samba配置文件 匿名访问2 3 2 启动Samba服务2 3 4用户密码
  • k8s多master节点使用二进制部署群集

    目录 一 K8S 多节点部署1 1 拓补图与主机分配1 2 mster02部署1 2 1 复制master中的三个组件启动脚本kube apiserver service kube controller manager service ku
  • K8S网站页面的搭建与证书优化配置

    一 下载官方的YAML 文件 五个文件各自的作用 dashboard configmap yaml 配置文件 dashboard deployment yaml 部署 dashboard rbac yaml 授权管理 一般来说要绑定角色 d
  • kubectl管理与项目的完整周期

    目录 一 kubectl管理二 项目的完整周期2 1 创建项目2 2 项目的发布2 3 更新版本2 4 版本回滚2 5 删除资源 一 kubectl管理 Kubectl是管理k8s集群的命令行工具 xff0c 通过生成的json格式传递给a
  • 学习记录:Ubuntu系统安装远程控制软件teamviewer

    一 teamviewer安装包下载 1 下载官方地址 xff1a https www teamviewer cn cn download linux 2 百度网盘下载地址 xff1a 链接 xff1a https pan baidu com
  • 结构体的内存对齐

    之前我们都知道int类型大小是4个字节 xff0c char类型为1个字节 xff0c double为8个字节等等 但是结构体是由很多类型组成的 xff0c 那么它的大小是多少呢 xff1f 是所有类型相加之和还是另有算法 xff1f 接下