小心内存对齐

什么是内存对齐?

CPU在读取内存地址的时候,一定按照一定的偏移量去读取,不知道你发现了没有,我们没有看到一个变量的大小是 3 个字节的,都是 1 个字节,2个字节,4个字节,8个字节,16个字节,32个字节。

为什么会这样呢?因为CPU设计的时候,没有一个 3 、5、7、9这样的模子,因为设计这样的模子非常费劲。

为什么要内存对齐?

之前网上有一个一个例子,如果一个变量int 的起始地址偏移是3,那么CPU要取这个地址上的数据,需要取两次,为什么呢?

640?wx_fmt=png假设一个变量 在内存的位置 从地址 1开始存放数据,因为这个是int类型,它占用4个字节的内存空间。

我们用一个int 的模子「int模子是4个字节」来卡这个数据,实际上是这样操作的,第一次卡模子,只能从0开始640?wx_fmt=png第二次卡模子,再从3位置开始640?wx_fmt=png从图片上可以明显看出来,我们需要CPU卡两次模子,才取到在内存里面的 int 变量

如果int 是按照内存对齐的方式存放的呢?

640?wx_fmt=png很明显,我们只需要卡一次模子就可以取到数据了。

内存对齐引发的问题

前两天,我们群上有一个同学,发了一份这样的代码出来,代码写得还是有一点风骚的,这位同学说,这个代码在A单片机上运行得非常OK,也已经出货了几万台了,但是这个代码移植到单片机B上后,就挂了,大家帮忙看看这个代码有什么问题?

uint8_t buf[16];	
uint8_t i;	
uint16_t data;	for (i=0; i<16; i+=2)	
{	data = *((uint16_t *)&buf[i]);	
}

问题的原因

经过一段激烈的讨论,后面发现是内存对齐的问题,一个群友画了一个图,写的很清楚了,因为char 是对单字节对齐的,所以没有问题,但是uint16_t 默认是对双字对齐的,所以如果初始地址是奇数的话,最后就出现内存越界了。640?wx_fmt=png

一个图片说明不同数据类型的内存对齐

640?wx_fmt=png

使用#pragma pack()限定内存对齐

我们可以使用宏 #pragma pack() 来指定内存对齐的方式,这里我就不展开说明了,如果说明太多了,后面用一个文章来单独说明,喜欢了解的同学可以百度看看,内容还是比较多的。

内存对齐可以提升CPU效率

我们知道单字节对齐的效率应该是最低的,我给两个代码给大家看看,比较一下,单字节和双字节内存对齐对CPU效率的影响。

单字节对齐函数

void Munge8( void ∗data, uint32_t size ) {	uint8_t ∗data8 = (uint8_t∗) data;	uint8_t ∗data8End = data8 + size;	while( data8 != data8End ) {	∗data8++ = ‑∗data8;	}	
}

双字节对齐函数

void Munge16( void ∗data, uint32_t size ) {	uint16_t ∗data16 = (uint16_t∗) data;	uint16_t ∗data16End = data16 + (size >> 1); /∗ Divide size by 2. ∗/	uint8_t ∗data8 = (uint8_t∗) data16End;	uint8_t ∗data8End = data8 + (size & 0x00000001); /∗ Strip upper 31 bits. ∗/	while( data16 != data16End ) {	∗data16++ = ‑∗data16;	}	while( data8 != data8End ) {	∗data8++ = ‑∗data8;	}	
}

这个代码大家可以直接拿去执行试试,最终的结果如下面的图片

640?wx_fmt=png

果修改成 4 字节对齐的话,结果将会更加有意思

四字对齐函数

void Munge32( void ∗data, uint32_t size ) {	uint32_t ∗data32 = (uint32_t∗) data;	uint32_t ∗data32End = data32 + (size >> 2); /∗ Divide size by 4. ∗/	uint8_t ∗data8 = (uint8_t∗) data32End;	uint8_t ∗data8End = data8 + (size & 0x00000003); /∗ Strip upper 30 bits. ∗/	while( data32 != data32End ) {	∗data32++ = ‑∗data32;	}	while( data8 != data8End ) {	∗data8++ = ‑∗data8;	}	
}

640?wx_fmt=png他们的效率主要体现在字节不对齐的时候,如果字节默认已经是对齐的时候,那效果更是快得飞起。

参考

https://developer.ibm.com/articles/pa-dalign/

留个问题

上面有问题的代码如何修改?

回答正确的前三名,我发心意红包

640?wx_fmt=jpeg

640?wx_fmt=jpeg

扫码或长按关注

回复「 加群 」进入技术群聊

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

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

相关文章

JavaScript获取select下拉框中的第一个值

JavaScript获取select下拉框中的第一个值 1、说明 获取select下拉框中的第一个值 2、实现源代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns&quo…

好用的平板电脑_支架里的变形金刚让手机、电脑、平板更好用!6种角度,1秒切换...

六 月 惊 喜戳 这 里嗨&#xff0c;我是专注研究数码3C产品的小嘻~对于当代人来说&#xff0c;办公、学习、娱乐离不开三件宝&#xff1a;手机、平板、电脑。手机不离手&#xff0c;沟通工作、看剧、刷抖音&#xff0c;没留神几个小时就过去了&#xff0c;放下手机的时候就觉得…

推荐一位AI技术人

今天推荐认识的一个朋友&#xff0c;推荐的原因很简单&#xff0c;因为他非常喜欢篮球&#xff0c;正统校队篮球队员&#xff0c;这个AI相关的公众号一直是他个人运营&#xff0c;写了非常多的文章&#xff0c;如果大家有在学习AI相关的知识&#xff0c;强烈推荐关注。AI蜗牛车…

如何 给给软件开发 添加 代理_敏捷开发是如何被跑偏的

今天聊聊敏捷软件过程。先说结论&#xff1a;据我观察&#xff0c;至少有60%的团队误用了敏捷软件过程&#xff0c;或者说至少60%的团队在进行伪敏捷开发。与大家通常的认知是相反的&#xff0c;敏捷过程并不是一个非常容易实践或者实施的过程规范。通常来讲&#xff0c;没有天…

在实时操作系统里随便写代码都能硬实时吗?

这是转发宋老师写的文章&#xff0c;我也是刚知道&#xff0c;宋老师跟我一样也是养娃的人了&#xff0c;国庆期间&#xff0c;看看文章&#xff0c;看看升升国旗。很久没有写技术文章了&#xff0c;做码农难&#xff0c;做养娃的码农更难&#xff0c;趁着娃看动画片的机会&…

python 数据分析 实际案例_python实战案例:超市营业额数据分析

实战是学习的最好途径&#xff0c;效率最高&#xff0c;本文不是很长&#xff0c;通过小小的练习&#xff0c;让大家综合运用基础知识&#xff0c;加深印象巩固记忆。一、读入数据&#xff0c;了解数据本数据随机生成的假数据&#xff0c;读者可以自己造&#xff0c;也可以通过…

台达n2系列变频器_台达变频器C2000系列在Profibus网络中的应用

基本介绍现场总线就是顺应信息技术的发展趋势和工业控制系统的分散化、网络化、智能化要求而发展起来的新技术&#xff0c;它的出现和发展已经成为全球工业自动化技术的热点之一&#xff0c;受到全世界和工业界的普遍重视。现场总线(Fieldbus)技术是实现现场级控制设备数字化通…

CentOS 6.8 虚拟机安装详解

第一步&#xff1a;安装 VMware 官方网站&#xff1a;www.vmware.com 下载百度云链接&#xff1a;http://pan.baidu.com/s/1bphDOWv 密码&#xff1a;0zix VMware 是一个虚拟 PC 的软件&#xff0c;可以在现有的操作系统上虚拟出一个新的硬件环境&#xff0c;相当于模拟出一台新…

unittest里discover用法_unittest框架核心要素及应用

1. unittest核心要素unittest介绍测试框架&#xff0c;不仅仅用于单元测试python自动的测试包用法和django.test.TestCase类似1.1【知道】unittest介绍和核心要素1.2【掌握】unittest核心要素的使用""" 1. 测试用例 2. 容器&#xff0c;容器添加测试用例 3. 运行…

void函数调用时显示不允许使用不完整的_4位数码管显示模块驱动

TM1637四位数码管模块是一个带时钟点的4位共阳数码管(0.36英寸)的显示模块&#xff0c;驱动芯片为TM1637&#xff0c;驱动方式为IIC&#xff0c;因此只需2根信号线即可使单片机控制4位8段数码管(数码管8级亮度可调)。模块特点如下&#xff1a;显示器件为4位共阳数码管数码管8级…

在线就能用的Linux我给你找好了

今天的天气真的是超级爽&#xff0c;秋日的凉风吹在脸上真的太美了&#xff0c;好不容易的假期&#xff0c;希望大家都玩得开心&#xff0c;今天分享一篇文章&#xff0c;是守望兄的&#xff0c;总结了几个在线的Linux&#xff0c;喜欢的同学&#xff0c;可以保存下来&#xff…

mysql访问类型最好的_【干货满满】最全的MySQL性能指南(一):选择最佳的数据类型...

对于 MySQL 数据库来说&#xff0c;好的逻辑表和物理表的规划至关重要&#xff0c;我们需要根据查询语句来针对性地设计 Schema &#xff0c;没有万能好用的 Schema。一个 denormalized 的 schema 可以在某些场景下加速语句查询&#xff0c;但是放在其他应用场景下就会适得其反…

测试两个主机之间的连通性_借助网络测试神器极速解决网络故障

时下&#xff0c;网络使用越来越频繁&#xff0c;随之遇到网络故障的情况也多起来&#xff0c;那么诊断网络故障就成了必不可少的一环&#xff0c;投诉和求助是一种基本的方法&#xff0c;但有时太过缓慢&#xff0c;有些时候自己可以快速搞定&#xff0c;检查到故障原因所在&a…

随想,对嵌入式职场建议

guoqingjie已经过去两天了&#xff0c;因为楠哥生病&#xff0c;我们搁浅在了深圳&#xff0c;不过相比在路上的奔波&#xff0c;待在家里感觉惬意不少&#xff0c;不用在路上各种操心&#xff0c;之前上班感冒&#xff0c;身体处在亚健康状态&#xff0c;睡了两天身体也恢复一…

java可达性_java垃圾回收机制--可达性算法

先说一些题外话&#xff0c;Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区&#xff0c;这些区分为线程私有区和线程共享区1、线程私有区a、程序计数器记录正在执行的虚拟机字节码指令地址。此区域是是唯一一个在java虚拟机规范中没有规定任何Ou…

为什么要有uboot?

一、为什么要有uboot1.1、计算机系统的主要部件(1)计算机系统就是以CPU为核心来运行的系统。典型的计算机系统有&#xff1a;PC机&#xff08;台式机笔记本&#xff09;、嵌入式设备&#xff08;手机、平板电脑、游戏机&#xff09;、单片机&#xff08;家用电器像电饭锅、空调…

华为路由器上有没有mac表_MAC地址表、ARP缓存表、路由表及交换机、路由器基本原理...

MAC地址表说到MAC地址表&#xff0c;就不得不说一下交换机的工作原理了&#xff0c;因为交换机是根据MAC地址表转发数据帧的。在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表&#xff0c;交换机就是根据这张表负责将数据帧传输到指定的主机上的。交换机的…

#define的高级用法

来源&#xff1a;嵌入式大杂烩地址&#xff1a;https://blog.csdn.net/xiaoxu2050/article/details/82893476一、宏的定义与撤销需要注意的是&#xff1a;&#xff08;1&#xff09;宏定义应注意添加括号&#xff0c;这样语义会比较清晰。&#xff08;2&#xff09;使用#undef可…

python读取csv文件_python3.0读取csv文件

创建CSV文件&#xff0c;可以打开excel文件&#xff0c;创建表格以后&#xff0c;另存为csv文件(以逗号分隔的文件)以文本格式打开&#xff0c;发现是用逗号分隔的用python读取csv文件&#xff0c;首先要引入一个库:csvimport csvdef getCsvFile(strpath):with open(strpath, &…

直击中关村创业大街,新街头霸王来了

中国的硅谷在北京中关村。如今&#xff0c;中关村中正在酝酿硅谷中的硅谷&#xff0c;这里将不断诞生最前卫最现代的互联网和移动互联网创业公司&#xff0c;他们当中极可能孵化出中国互联网企业未来10年的新的BAT。这个硅谷中的硅谷。就是中关村创业大街。这条街在过去15年是北…