struct自然边界上的内存对齐
来源:互联网 发布:小米3qq健康 数据来源 编辑:程序博客网 时间:2024/05/01 07:45
内存对齐大多数情况对程序员是透明的,是由编译器自动处理。在C里面允许我们干预内存对齐。而由于内存对齐的原因,巧妙的设计结构体也是非常必要的。
关于内存对齐问题,字、双字和四字在自然边界上不需要在内存中对齐,对字、双字和四字来说自然边界分别是奇数地址,可以被2整除地址,和被4整除地址。 而数据访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存只作一次访问;这是原因之一,另外不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。因此为提高程序性能,数据结构尤其是栈应尽可能在自然边界上对齐。
一个字起始地址是奇数(当然偶数也行)但却没有跨越字边界,被认为是对齐的。下面来看个例子:
struct TestStruct1
{
char c1;
short s;
char c2;
int i;
};
如果紧凑排列,c1地址是0,那么s:为1; c2:为3;i为4,整个结构体大小为8;但很可惜,s为2,c2为4;i为8;而整个结构体大小为12。编译器将未对齐的s,c2,i成员后移,使之对齐到自然边界上,从而也让大小由8变成了12。
如果是这样的结构:
struct TestStruct2
{
char c1;
char c2;
short s;
int i;
};
c1地址如果是0,接下来到c2,由于是一个字自然边界是奇数,所以对齐不需后移,故c2地址为1;到s,双字自然边界被2整除,也对齐,不需后移,地址为2;到i,四字自然边界被4整除,不需后移,地址为4;结构体大小为8。
接下来再看一个例子:
struct TestStruct3
{
char c1;
int j;
char c2;
};
c1地址如果是0,接下来由于j四字自然边界被4整除,而没有对齐,故地址后移3位,为4;到c2,一字自然边界是奇数不用后移,地址为8,整个结构体应该为9,但很可惜,其实大小为12。
为什么呢,原因是前面是int,申请的大小为4,以后申请的大小应该都为4。这样解释貌似合理。
再看一个例子:
struct TestStruct4
{
char c1;
int j;
char c2;
char c3
};
其中c1,j,c2和TestStruct3一样,到c3,由于c2申请的4个只用了1个,而又有c3自然边界是奇数,故可以不用后移,地址为9,当然结构体大小也不变为12。
若结构体变成这种:
struct TestStruct5
{
char c1;
int j;
char c2;
short i;
};
则在最后的i,自然边界为偶数,而又有c2申请了4个只用了1个,3个够用,所以可以只后移一位,地址为10,结构体大小依旧为12。
再看最后一个例子:
struct TestStruct6
{
char c1;
int j;
short i1;
char c2;
short i2;
};
c1如果地址0,那么j为4,i1为8,char c2为10,接下来的地址为11,由于i2自然边界是偶数,则后移到12,这时i1申请的4个地址全部用完,这时i2申请的大小应该为多少呢,实验证明:还是申请4。结构体大小为:16。
以上看来,结构体的设计技巧对内存空间的管理还是很重要的,
而在C中允许干涉内存对齐的“家庭纠纷“的方法就是用预处理命令#pragma,在所有预处理命令中,它可能也是最复杂的,它的作用是设定编译器的状态或是指示编译器完成一些特定的动作,关于这个命令的用法,我还没详细了解多少。
这里用到的是:#pragma pack(n) 和#pragma();前者是编译器按n个字节对齐,后者是取消编译器的自定义字节对齐方式,一般需要对一个对象自定义,则将其写在两者之间即可。
struct TestStruct1
{
};
如果是这样的结构:
struct TestStruct2
{
};
接下来再看一个例子:
struct TestStruct3
{
};
为什么呢,原因是前面是int,申请的大小为4,以后申请的大小应该都为4。这样解释貌似合理。
再看一个例子:
struct TestStruct4
{
char c2;
char c3
};
struct TestStruct5
{
char c2;
short i;
};
再看最后一个例子:
struct TestStruct6
{
short i1;
char c2;
short i2;
};
本文转载自关于内存对齐
0 0
- struct自然边界上的内存对齐
- 关于struct的边界对齐问题
- 关于 struct 和 union 存储时内存边界对齐的问题(二)
- 自然对齐:sizeof struct, union
- struct的内存对齐(转)
- struct的内存对齐方式
- struct结构的内存对齐
- 结构体struct的自然对齐问题(经典)
- 结构体struct的自然对齐问题(经典)
- 关于struct结构体自然对齐的思考
- 内存对齐(自然对齐)
- struct自然对齐和指定对齐
- C#中struct的内存对齐
- 关于 Struct 内存对齐的几个例子
- struct的内存对齐(转)
- struct的内存对齐详细讲解
- struct成员的内存对齐问题:
- 关于struct的内存对齐问题
- Linux那些事儿 之 戏说USB(12)接口是设备的接口(一)
- java细节,你注意到了多少?
- android端调用服务端的webservice接口,报错总结。
- Android:自定义toast
- NSNotificationCenter 编程简介
- struct自然边界上的内存对齐
- 自行控制LoadRunner的socket协议性能测试
- JDK1.4读取word中的表格
- Xcode变更应用名称
- 获取tableviewCell在当前屏幕中的坐标值
- SQL - Using Cross Joins
- 无源最短路径之--地铁换乘
- Shell脚本常识--(条件判断)
- 循环赛日程表《分治法》