内存中的数据对齐

数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍。DWORD数据的内存起始地址能被4除尽,WORD数
据的内存起始地址能被2除尽。x86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据时,会在内部进行一系列
的调整。这些调整对于程序来说是透明的,但是会降低运行速度,所以编译器在编译程序时会尽量保证数据对齐。同样一
段代码,我们来看看用VC、Dev C++和LCC这3个不同的编译器编译出来的程序的执行结果:

这是用VC编译后的执行结果:

变量在内存中的顺序:b(1字节)—a(4字节)—c(4字节)。
这是用Dev C++编译后的执行结果:

变量在内存中的顺序:c(4字节)—中间相隔3字节—b(占1字节)—a(4字节)。
这是用LCC编译后的执行结果:

变量在内存中的顺序:同上。
3个编译器都做到了数据对齐,但是后两个编译器显然没VC“聪明”,让一个char占了4字节,浪费内存。

以下代码为32位机器编译,数据是以4字节为对齐单位,这两个类的输出结果
为什么不同?[中国著名软件企业JS公司2008年4月面试题]

解析:在访问内存时,如果地址按4字节对齐,则访问效率会高很多。这种现象的原因
在于访问内存的硬件电路。一般情况下,地址总线总是按照对齐后的地址来访问的。例如你
想得到0x00000001开始的4字节内容,系统首先需要以0x00000000读4字节,从中取得3字
节,然后再用0x00000004作为开始地址,获得下一个4字节,再从中得到第一个字节,两次
组合出你想得到的内容。但是如果地址一开始就是对齐到0x00000000,则系统只要一次读写
即可。
     考虑到性能方面,编译器会对结构进行对齐处理。考虑下面的结构:

直观地讲,这个结构的尺寸是sizeof(char)+sizeof(int)=6,但是在实际编译下,这个结构
尺寸默认是8,因为第二个域iValue会被对齐到第4个字节。
在VC中,我们可以用pack预处理指令来禁止对齐调整。例如,下面的代码将使得结构尺
寸更加紧凑,不会出现对齐到4字节问题:

对于这个pack指令的含义,大家可以查询MSDN。请注意,除非你觉得必须,否则不要
轻易做这样的调整,因为这将降低程序的性能。目前比较常见的用法有两种,一是这个结构
需要被直接写入文件;二是这个结构需要通过网络传给其他程序。
注意:字节对齐是编译时决定的,一旦决定则不会再改变,因此即使有对齐的因素在,
也不会出现一个结构在运行时尺寸发生变化的情况。
在本题中,第一种类的数据对齐是下面的情况:

第二种类的数据对齐是下面的情况:

答案:B类输出12字节,C类输出8字节。

求解下面程序的结果。[中国著名通信企业H公司面试题]

解析:因为静态变量是存放在全局数据区的,而sizeof计算栈中分配的大小,是不会计
算在内的,所以sizeof(A1)是4。
● 为了照顾数据对齐,int大小为4,char大小为1,所以sizeof(A2)是8。
● 为了照顾数据对齐,float大小为4,char大小为1,所以sizeof(A3)是8。
● 为了照顾数据对齐,float大小为4,int大小为4,char大小为1,所以sizeof(A3)是12。
● 为了照顾数据对齐,double大小为8,float大小为4,int大小为4,char大小为1,所以
sizeof(A3)是24。
答案:4,8,8,12,24。

时间: 2024-08-04 18:19:40

内存中的数据对齐的相关文章

简单了解:在内存中的数据

内存原理 开启电源,启动BIOS,CPU工作,调用内存,内存跟硬盘索要资源 当你点击一个文件的时候数据经过数据总线传达到CPU,CPU发送指令到内存,内存那里会跟硬盘沟通,问他有没有这个东西,他说有,你就会看到这个文件夹里面是什么东西. (Xee:RAM 是随机存取存储器,它的特点是易挥发性,即掉电失.--妈蛋,难怪一断电,我的东西没保存,就找不到了-- 既然内存是用来存放当前正在使用的(即执行中)的数据和程序,那么它是怎么工作的呢?我们平常所提到的计算机的内存指的是动态内存(即DRAM),动态

ffmpeg 从内存中读取数据

http://blog.csdn.net/leixiaohua1020/article/details/12980423 ffmpeg一般情况下支持打开一个本地文件,例如"C:\test.avi" 或者是一个流媒体协议的URL,例如"rtmp://222.31.64.208/vod/test.flv" 其打开文件的函数是avformat_open_input(),直接将文件路径或者流媒体URL的字符串传递给该函数就可以了. 但其是否支持从内存中读取数据呢?这个问题困

REDIS 勿删除rdb文件如何从内存中恢复数据

redis的数据是在内存中的,如果redis重启或间隔一定时间redis会把内存保存在硬盘上的一个.rdb文件中做持久化,以前刚刚开始用redis的时候,不小心把.rdb文件给误删除了,但你只要正常save或者重启redis,rdb文件会自动生成. 但随着线上业务增加,redis的数据会越来越大,在用这种方法会出现错误,不能把内存中的数据保存到rdb文件中,这时需要只要做以下几步,就可以恢复rdb文件了: 进入到redis端口,info查看配置信息 进入redis端口 执行 config set

GLPI资产菜单中的数据对齐修改

今天安装了glpi给同事使用,结果发现资产表格中的数据默认是左对齐,字段是居中对齐,看起来非常不舒服,因为glpi是开放源代码的系统,经过一番努力,终于找到了这个表格对齐的代码.文件路径: glpi\css\styles.css 然后查找.tab_cadrehov 标签,以将其中的text-align: left 属性修改为center即可. .tab_cadrehov { margin: 10px auto; border: 0; /*默认是left;*/ text-align: center

Android---35---openFileInput、openFileOutput获取手机内存中的数据

openFileOutput和openFileInput 获取手机内存中的文件而不是SD卡中的. Context提供了两个方法来打开本应用程序的数据文件夹里的文件I/O流. openFIleInput(String name):name文件对应的输入流 openFileOutput(String name,int mode):name文件对应的输出流 其中输出流中的第二个参数表示打开文件的模式,也可以称作权限: MODE_PRIVATE:该文件只能被当前程序读写 MODE_APPEND:以追加的

第二十一章、使用查询表达式来查询内存中的数据

什么是语言集成查询(LINQ) 对从应用程序代码中查询数据的机制进行了“抽象”.这个功能称为“语言集成查询”(Language Integrated Query). LINQ的设计者大量借鉴了关系数据库管理系统(例如Microsoft SQL Server)的处理方式,将“数据库查询语句”与“数据在数据库中的内部格式”分隔开.LINQ的语法和语义和SQL很像,具有许多相同的优势.要查询的数据的内部结构发生改变后,不必修改查询代码.注意,虽然LINQ和SQL看起来很像,但LINQ更加灵活,而且能处

Ultra Edit中的数据对齐

有时会用到Ultra Edit的数据对齐功能.比如,要求64个符号一组,从低位开始对齐.这时,如果数据长度不是一行长度的整数, 就会产生高位对齐.低位不足的问题.为了调整,往往需要逐行调整,很不方便. 有一个优化的方法,先计算数据长度除以"行长度"的余数,然后在数据首位前补足零,以保证整除.之后自动对齐,没有低位不足 的问题.

Xcode如何查看内存中的数据

在  debug 模式下如何在断点处,查看字符指针变量内存中的值,像vs2008的调试工具一样的内存查看器,现在只能查看第一个内存中的值可以在输出窗口采用gdb命令:x /nfu <addr> n表示要显示的内存单元的个数 ----------------------------------------- f表示显示方式, 可取如下值:x 按十六进制格式显示变量d 按十进制格式显示变量u 按十进制格式显示无符号整型o 按八进制格式显示变量t 按二进制格式显示变量a 按十六进制格式显示变量i 指

结构体中的数据对齐

c语言结构中需要注意的就是数据存储的对齐方式. 对齐的好处:对齐主要是为了方便数据的访问,提高计算机的处理速度,但同时它会浪费内存空间. CPU的优化规则大致是这样的:对于n字节的元素,它的首地址能被n整除,才能获得最好的性能. 对齐的使用原则: 1.一般的基本对齐原则是按着最大的基本类型的长度进行对齐.较小的元素可以组合起来填充一段内存,实现基本的对齐.前提是其满足条件2. 2.结构体中的元素也要满足一定的分布条件,就是元素的存储起始地址要满足能够整除该元素类型的长度. 3.在结构体中存在结构