已阅读5页,还剩3页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
会“失算”的Sizeof() !很多情况下我们会用sizeof来计算变量的大小,我们都觉得很方便,sizeof()一下大小就知道了,殊不知sizeof() 也会“骗人”。请看下面的例子:#includestruct TestStruct1int t1;char t2;double t3;short t4; testPack;int main()coutsizeof(t1)=sizeof(testPack.t1)endl;coutsizeof(t2)=sizeof(testPack.t2)endl;coutsizeof(t3)=sizeof(testPack.t3)endl;coutsizeof(t4)=sizeof(testPack.t4)endl;coutsizeof(t1+t2+t3+t4)=sizeof(testPack.t1)+sizeof(testPack.t2)+sizeof(testPack.t3)+sizeof(testPack.t4)endl;coutsizeof(TestStruct1)= sizeof(testPack)endl;coutendl;return 0;我们定义一个结构体,计算它里面的元素大小之和和结构体大小,按照我们的思维这两者应该是一样的但是你会惊人地发现相结果去甚远。为什么呢?别急,继续往下看#include#pragma pack(1)struct TestStruct1int t1;char t2;double t3;short t4; testPack;#pragma pack()int main()coutsizeof(t1)=sizeof(testPack.t1)endl;coutsizeof(t2)=sizeof(testPack.t2)endl;coutsizeof(t3)=sizeof(testPack.t3)endl;coutsizeof(t4)=sizeof(testPack.t4)endl;coutsizeof(t1+t2+t3+t4)=sizeof(testPack.t1)+sizeof(testPack.t2)+sizeof(testPack.t3)+sizeof(testPack.t4)endl;coutsizeof(TestStruct1)= sizeof(testPack)endl;coutendl;return 0;呵呵呵 看到了我们想要看到的结果 你会发现程序中多了两行代码,这是什么东东?一打听才知道,原来这就是传说中的字节的对齐方式#pragma pack(1)/设置对齐字节#pragma pack()/回复对齐状态(还原为 默认对齐)指定packing的数值,以字节为单位;缺省数值是8,合法的数值分别是1、2、4、8、16。解释:现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取。比如有些架构的CPU在访问 一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐.其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那 么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数 据。重要规则:1,复杂类型中各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个类型的地址相同;2,每个成员分别对齐,即每个成员按自己的方式对齐,并最小化长度;规则就是每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐;3,结构、联合或者类的数据成员,第一个放在偏移为0的地方;以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度两个中比较小的那个进行;也就是说,当#pragma pack指定的值等于或者超过所有数据成员长度的时候,这个指定值的大小将不产生任何效果;4,复杂类型(如结构)整体的对齐是按照结构体中长度最大的数据成员和#pragma pack指定值之间较小的那个值进行;这样在成员是复杂类型时,可以最小化长度;5,结构整体长度的计算必须取所用过的所有对齐参数的整数倍,不够补空字节;也就是取所用过的所有对齐参数中最大的那个值的整数倍,因为对齐参数都是2的n次方;这样在处理数组时可以保证每一项都边界对齐;这里需要明白几个概念:1.数据类型自身的对齐值:每个成员按其类型的对齐参数(通常是这个类型的大小)。2.指定对齐值:#pragma pack (value)时的指定对齐值value。 3.结构体或者类的自身对齐值:其数据成员中自身对齐值最大的那个值。4.数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。有了这些值,我们就可以很方便的来讨论具体数据结构的成员和其自身的对齐方式。有效对齐值N是最终用来决定数据存放地址方式的值,最重要。有效对齐N,就是表示“对齐在N上”,也就是说该数据的存放起始地址%N=0.而数据结构中的数据变量都是按定义的先后顺序来排放的。第一个数据变量的起始地址就是数据结构的起始地址。结构体的成员变量要对齐排放,结构体本身也要根据自身的有效对齐值圆整(就是结构体成员变量占用总长度需要是对结构体有效对齐值的整数倍,结合下面例子理解下面让我们来试试上面说的东西,看看上面是不是胡扯的?第一例子中采用的是系统默认的对齐参数。我们不知道是多少,等我们学会了再来算吧第二例中对齐对齐参数为1 第一个 int 对齐自身值为4,那么有效对齐值为 1 我们假定这个结构从0x0000开始写入,那么int t1 放在0x00000x0003,是整个结构体的首地址,0x0000%1 = 0; 第二个char t2 放在0x0004,0x0004%1=0;在这个例子中有效对齐值都为1 ,所以该结构数据在内存中任意位置都可以防止,是完全一个接着一个排列的,所以看到的是我们期望的样子。#include#pragma pack(2)struct TestStruct1int t1;char t2;double t3;short t4; testPack;#pragma pack()int main()coutsizeof(t1)=sizeof(testPack.t1)endl;coutsizeof(t2)=sizeof(testPack.t2)endl;coutsizeof(t3)=sizeof(testPack.t3)endl;coutsizeof(t4)=sizeof(testPack.t4)endl;coutsizeof(t1+t2+t3+t4)=sizeof(testPack.t1)+sizeof(testPack.t2)+sizeof(testPack.t3)+sizeof(testPack.t4)endl;coutsizeof(TestStruct1)= sizeof(testPack)endl;coutendl;return 0;在这个例子中 第一个 int t1 自身对齐值是4,指定对齐值是2 ,所以有效对齐值是2且 0x0000%2 = 0。可以放在这个位置,所以第一个数放在 0x00000x0003 0x 中,char t2 自身对齐值为1 小于指定对齐值,有效对齐值为1,现在我们期望的是把这个数放在0x0004,0x0004%1 = 0。所以t2能放在0x0004。第三个数 double t3 占8 个字节,自身对齐值为8,指定对齐值为2 所以有效对齐值为2,我们期望能把这个数从0x0005开始存放,但是0x0005%2 不等于0,所以这个数不能从0x0005开始放。0x0006%2 = 0 ,而且紧靠前一个数,所以,t3 要从0x0006开始存放,0x00060x000d 用来存放t3。第四个数short t4 自身对齐值为2有效对齐值也为2,我们期望的是从0x000e 开始存放,0x000e%2 = 0。所以这个值能放在0x000e0x000f。那么对整个结构体来说,总长度 0x00000x000f 一个16个字节,自身对齐值为 8 (成员里面最长的那个),指定对齐值为2 所以有效对齐值为2 16%2 =0。所以0x00000x000f所存放的就是结构体TestStruct1。咋样?明白了不? 啥?还不明白?那继续!#include #pragma pack(4)struct TestStruct1int t1;char t2;double t3;short t4; testPack;#pragma pack()int main()coutsizeof(t1)=sizeof(testPack.t1)endl;coutsizeof(t2)=sizeof(testPack.t2)endl;coutsizeof(t3)=sizeof(testPack.t3)endl;coutsizeof(t4)=sizeof(testPack.t4)endl;coutsizeof(t1+t2+t3+t4)=sizeof(testPack.t1)+sizeof(testPack.t2)+sizeof(testPack.t3)+sizeof(testPack.t4)endl;coutsizeof(TestStruct1)= sizeof(testPack)endl;coutendl;return 0;这个例子中 指定对齐值为4, 第一个int t1 自身对齐值为4,所以有效对齐值为4,我们期望从0x0000开始存放,因为0x0000%4 =0。所以t1 能从0x0000开始存放,t1 存放状态为0x00000x0003 第二个char t2,有效对齐值为1,期望存放在0x0004,0x0004%1 =0,所以能存放在0x0004,第三个 double t3 有效对齐值为 4 期望从0x0005开始存放,可是你会杯具第发现 0x0005%4不等于0 ,那咋办?找0x0005附近,又能整除4的呗,0x0008就被你发现了,所以t3 存放在0x00080x000f。最后一个short,有效对齐值为2 我们期望从0x0010开始存放,结果发现0x0010%2=0。所以short t4 存放在0x00100x0011。对整个结构体来说。自身对齐值为8,所以有效对齐值为4 结构体已存数据长度 0x0000x0011 一共是18 字节,可是18%4要余2啊,咋办?那就找离它最近而又能整除4的数呗,那就是20了。所以0x00110x0012也光荣地属于结构体TestStruct1了。所以这个结构体的sizeof()就为20 了#include#pragma pack(8)struct TestStruct1int t1;char t2;double t3;short t4; testPack;#pragma pack()int main()coutsizeof(t1)=sizeof(testPack.t1)endl;coutsizeof(t2)=sizeof(testPack.t2)endl;coutsizeof(t3)=sizeof(testPack.t3)endl;couts
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年中国脉动真空灭菌器行业市场占有率及投资前景预测分析报告
- 十五五规划建议专题测试及答案一
- 2025上海交通大学医学院教育发展基金会人员招聘3人考试笔试备考题库及答案解析
- 2025江苏苏州狮山商务创新区国有企业招聘5人考试笔试备考题库及答案解析
- 2026内蒙古锡林郭勒盟多伦县第三中学(自治区示范性高中)赴内蒙古师范大学招聘教师3人考试笔试模拟试题及答案解析
- 2026广西南宁市第三人民医院招聘笔试考试参考试题及答案解析
- 2025湖北随州北星汇能产业发展有限公司招聘8人笔试考试备考题库及答案解析
- 黑龙江工业学院2025年下半年公开招聘工作人员(人事代理)36人考试笔试参考题库附答案解析
- 2025广东中山火炬高技术产业开发区管理委员会所属事业单位第二期招聘事业单位人员20人考试笔试备考试题及答案解析
- (人教2024版)英语八年级上册Unit 4 大单元教学设计(新教材)
- 内蒙古农村信用社招聘考试(真题)
- 隧道工程施工质量常见问题及解决方案
- 2025年党校条例试题及答案详解
- 2025年国家能源集团企业文化考试题库及答案
- 看一次禁毒电影活动方案
- 2025太原迎泽区社区劳动保障协理员和城镇最低生活保障协理员招聘考试模拟试题及答案解析
- 消防公司企业简介
- 艾滋病免疫重建不全临床诊疗专家共识
- 优生优育进社区知识培训课件
- 网络安全攻防演练方案
- 设备安装安全生产培训课件
评论
0/150
提交评论