【补充1】字节对齐

文章目录

  • 1.字节对齐的基本概念
  • 2.字节对齐规则
  • 3.实践出真知(加大难度)
  • 4 位域

1.字节对齐的基本概念

(1)现代计算机中内存空间都是按照byte划分的,
从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,
但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,
这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。(2)对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。
一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。

显然在读取效率上下降很多。

2.字节对齐规则

先来看一个简单的例子

struct DATA
{short flag;int   data;
};
printf("DATA sizeof:%d\n", sizeof(DATA));
上面的输入会是多少呢?这里的输出是size=8,亲们可以复制代码测试看输出是多少。
那么问题来了,为什么这个结构的大小不是short(2字节)+int(4字节)=6字节呢?请看下面的对齐规则你便明白了。

(1).数据类型自身的对齐值:
对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
(2).结构体的自身对齐值:
其成员中自身对齐值最大的那个值(默认)。
(3).指定对齐值(这个对齐的值是可以人为控制的):

>#pragma pack(value) 	// 作用:C编译器将按照n个字节对齐。
#pragma pack()			// 作用:取消自定义字节对齐方式。
//或者
#pragma pack(push, value)	// 作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为value个字节对齐
#pragma pack(pop)           // 作用:恢复对齐状态
// 此时就使用指定对齐值 value。
// 两者区别:加入push和pop可以使对齐恢复到原来状态,而不是编译器默认;
//         可以说后者更优,但是很多时候两者差别不大。

(4).数据成员、结构体的有效对齐值:
自身对齐值和指定对齐值中取最小的那个值作为对齐值。

在倒回去看例子,结构体DATA的对齐取的是4(int 4字节较大),所以前面的short就变成了占4个字节空间,所以sizeof(DATA)输出的是8了。
为什么short就变成占4字节空间了?刚开始也不太明白为什么short就变成占4字节空间了。继续看完下面的实践便明白了。

3.实践出真知(加大难度)

struct DATA1
{short 	flag1;int	  	data;short 	flag2;
};struct DATA2
{short 	flag1;short 	flag2;int     data;
};printf("DATA1 size:%d\n", sizeof(DATA1));
printf("DATA2 size:%d\n", sizeof(DATA2));

运行上面的程序,结果将是:

DATA1 size:12
DATA2 size:8

为什么会出现这样的结果呢?分析:
首先,两个结构体取的对齐数是4(int 4字节较大),在结构体DATA1进行存放时,假设是从地址0x00开始存放的,flag1(short)存放在在0x00-0x01里面,在前四个字节里面还剩下两个字节;紧接着是data(int),data(int)是四个字节,剩下的两个字节不够装data了。所以data(int)就新开了四个字节存放,所以他的地址就是0x04-0x07;最后是flag2(short),由于它只有两个字节,即0x08-0x09,他为了满足四字节对齐,所以它也空了两个字节。最终DATA1的内存为0x00-0x11;所以sizeof(DATA1)=12。
我们在来看DATA2,flag1(short)存放在0x00-0x01里面,前四个字节里面还剩下两个字节,紧接着是flag2(short),flag2(short)是两个个字节,前两剩下的两个字节正好存放下,存放在0x02-0x03,所以前四个字节将flag1和flag2存放好了;最后是data(int),data在紧接着的四个字节里存放,即0x04-0x07,所以最终DATA2的内存为0x00-0x07;所以sizeof(DATA2)=8。

[拓展]如何让结构体DATA1也变为8字节呢?那就是人为控制字节对齐数。
将上面的结构体改为如下

#pragma pack(push, 2)
struct DATA1
{short 	flag1;int	  	data;short 	flag2;
};
#pragma pack(pop)struct DATA2
{short 	flag1;short 	flag2;int     data;
};printf("DATA1 size:%d\n", sizeof(DATA1));
printf("DATA2 size:%d\n", sizeof(DATA2));

修改后的输出为:

DATA1 size:8
DATA2 size:8

如上,我们便将DATA1的字节对齐数设置为2,这边便控制了DATA1的的字节数为8;可以在字节对齐数为2的基础上在此分析其构成,我这里就不在阐述了。

4 位域

结构体中,还有一个操作叫做位域,

struct A
{char  a : 2;short b : 3;int   c : 4;
};

在结构体A中,a的8位只有2位有效,b的16位只有3为有效,c的32位只有4位有效。
注意:位域必须存储在同种数据类型所占的字节中,不能跨两个同种数据类型所占的字节数。 也就是说,后面的数字不能大于前面类型的位数。 位域不会影响 sizeof() 的规则

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/842134.shtml

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

相关文章

MybatisPlus中自定义sql

背景 在开发过程中,可能会出现除了where条件,其它sql比较复杂,这时候就需要用到自定义sql了。 问题 如:用户状态为正常的数据年龄加一(所有用户年龄加一) 数据库中sql: UPDATE USER SET…

协变(List泛型作为方法参数时的父类子类问题)

有段时间没搞.net的项目了(没办法,谁让国内JAVA流行是事实)。最近又回归.net(哪里需要哪里搬~)。 接收到需求后,一顿输出,结果…咦?编译失败??? 错误信息: CS1503:参数1:无法…

Docker 常用命令大全!!

Docker 常用命令 一、启动类1. 启动 docker2. 关闭 docker3. 重新启动 docker4. docker 设置自启动5. 查看 docker 运行状态6. 查看 docker 版本号等信息7. docker 帮助 二、 镜像类1. 查看镜像2. 搜索镜像3. 拉取镜像4. 运行镜像5. 删除镜像6. 加载镜像7. 保存镜像 三、容器类…

react解决电脑分辨率及缩放导致页面变形的问题

此处借鉴Vue3 解决电脑分辨率及缩放导致页面变形的问题-CSDN博客: 新建devicePixelRatio.js: /*** description 校正windows页面在系统进行缩放后导致页面被放大的问题,通常放大比例是125%、150%* **/class DevicePixelRatio {constructor(…

python-opencv 边缘检测、直线检测、圆检测

文章目录 Canny算法霍夫变换-直线检测霍夫变换-圆形检测 Canny算法 除了将目标与背景分离开来,边缘检测也同样是一种图像分割方法,从分割结果来看,adaptiveThreshold函数显然就采取了类似边缘检测的划分方案。 Canny在1986年提出了一种边缘…

【源码】2024完美运营版商城/拼团/团购/秒杀/积分/砍价/实物商品/虚拟商品等全功能商城

后台可以自由拖曳修改前端UI页面 还支持虚拟商品自动发货等功能 前端UNIAPP 后端PHP 一键部署版本 获取方式: 微:uucodes

代码随想录算法训练营第四十一天|动态规划理论基础、509. 斐波那契数列、70. 爬楼梯、746. 使用最小花费爬楼梯

动态规划理论基础 什么是动态规划 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就…

X2Doris使用指南:界面化数据迁移工具 - 轻松实现整库迁移至Doris

什么是X2Doris X2Doris 是 SelectDB 团队开发的,专门用于将各种离线数据迁移到 Apache Doris 中的核心工具,该工具集 自动建 Doris 表 和 数据迁移 为一体,目前支持了 Apache Doris/Hive/Kudu/StarRocks 数据库往 Doris 或 SelectDB Cloud 迁…

Oracle AVDF(审计保险库和数据库防火墙)常见问题

此文是AVDF FAQ的翻译注解(斜体) 通用问题 审计库和数据库防火墙的最新版本是什么? Oracle Audit Vault 和 Database Firewall (AVDF) 的最新版本是版本更新 11 (AVDF 20.11)。请阅读公告博客和发行说明以了解更多详细信息。 Oracle Audit …

一屏万象,场景无限:蓝牙墨水屏标签多功能多场景应用带您领略未来

在数字化浪潮汹涌澎湃的今天,智能科技产品层出不穷,它们不仅极大地改变了我们的生活方式,更在无形中拓宽了我们的视野。而今,一款融合了创新技术与实用性于一体的蓝牙墨水屏标签,正以其多功能多场景应用的特性&#xf…

在GoDaddy网站托管上托管Next.js , npm项目步骤

要在GoDaddy网站托管上托管一个使用Next.js构建的npm项目,步骤: 1. 准备Next.js项目 确保Next.js项目已经准备好,并且可以在本地运行。可以使用以下命令来启动项目: npm install npm run build npm start2. 设置GoDaddy主机 登…

strstr的使⽤和模拟实现

strstr(function) Returnsa pointer to the irst occurrence of str2 in str1, or a null pointer if str2 is not part of str1. (函数返回字符串str2在字符串str1中第⼀次出现的位置)。 The matchingprocess doesnot include t…

无线麦克风什么品牌好?一文读懂无线领夹麦克风哪个品牌音质最好

​当我们谈论到演讲、表演或者录制视频时,一个高质量的无线麦克风能够使得整个体验提升至一个全新的水平。它不仅能够保证声音的清晰度和真实度,还能够让使用者在演讲或者表演时更加自信和舒适。基于对市场的深入研究和用户体验的考量,我挑选…

在微信公众号怎么添加留言板功能

在如今信息爆炸的时代,微信公众号已成为企业与用户互动的重要桥梁。如何在这个平台上脱颖而出,吸引用户的眼球,提升用户黏性,成为每一个公众号运营者都需要思考的问题。今天,我们就来聊聊如何在微信公众号中巧妙添加留…

车辆相关识别API优化您的车辆系统

车辆相关识别API是开发者们所需的重要工具,它们基于先进的计算机视觉和深度学习技术,提供了强大的车辆识别和分类能力。这些API能够从图像或视频中快速准确地识别和提取车辆的关键信息,如车辆型号、品牌、颜色等。对于开发者而言,…

1251. 平均售价

1251. 平均售价 题目链接:1251. 平均售价 代码如下: # Write your MySQL query statement below select p.product_id,round(ifnull(sum(units*price)/sum(units),0),2) as average_price from Prices as p left join UnitsSold as u on p.product_id…

机器学习:探索数据的魔法世界

课程链接:AI小天才:让你轻松掌握机器学习 引言: 在当今数字化的时代,数据无处不在,而机器学习则是解析、理解和利用这些数据的魔法钥匙。从自动驾驶到智能推荐系统,机器学习的应用无所不在,给我…

k8s问题

文章目录 本地搭K8s集群 bilibili什么是声明式API?kubectl apply Etcd数据库有什么特性,为什么K8S选用了Etcd数据库?K8S中一个node的生命周期是怎样的?服务发现机制介绍docker的实现原理介绍如果只是使用Linux命名空间进行分离&am…

【深度学习】最强算法之:人工神经网络(ANN)

人工神经网络ANN 1、引言2、人工神经网络(ANN)2.1 定义2.1.1 定义2.1.2 应用场景 2.2 核心原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝:鱼哥,看新闻没? 小鱼:新闻天天看,啥事大惊小怪的。 小屌…

Python数据分析-心脏病(随机森林预测分析)

本次案例分析用心脏病数据集来做随机森林模型预测 导入基本的数据分析包 import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score…