您的位置:首页 > 其它

变量的内存分配:内存对齐

2014-04-02 15:49 47 查看


数据结构还有变量等等都需要占有内存,在很多系统中,它都要求内存分配的时候要对齐,这样做的好处就是可以提高访问内存的速度。

#include <iostream>

2 using namespace std;

3

4 struct X1

5 {

6 int i;//4个字节

7 char c1;//1个字节

8 char c2;//1个字节

9 };

10

11 struct X2

12 {

13 char c1;//1个字节

14 int i;//4个字节

15 char c2;//1个字节

16 };

17

18 struct X3

19 {

20 char c1;//1个字节

21 char c2;//1个字节

22 int i;//4个字节

23 };

24 int main()

25 {

26 cout<<"long "<<sizeof(long)<<"/n";

27 cout<<"float "<<sizeof(float)<<"/n";

28 cout<<"int "<<sizeof(int)<<"/n";

29 cout<<"char "<<sizeof(char)<<"/n";

30

31 X1 x1;

32 X2 x2;

33 X3 x3;

34 cout<<"x1 的大小 "<<sizeof(x1)<<"/n";

35 cout<<"x2 的大小 "<<sizeof(x2)<<"/n";

36 cout<<"x3 的大小 "<<sizeof(x3)<<"/n";

37 return 0;

38 }

输出的结果:

1 long 4

2 float 4

3 int 4

4 char 1

5 x1 的大小 8

6 x2 的大小 12

7 x3 的大小 8

http://www.cppblog.com/cc/archive/2007/09/17/10765.html

在定义结构体x1,x2,x3时,由于变量的顺序不同,而导致分配的内存不同

内存是一个连续的块, 以每4个字节为一个对齐单位,来看一下x1,x2,x3在内存中的布局

对于x1,第一个是int型,它占4个字节,所以前面4格就满了,第二个是char型,它占第二个4字节组块的第一格,第三个是char型,它占第二个4字节组块的第二格,因为有内存对齐,所以输出结果为8而不是6.

对于x2,第一个类型是char型,它占用一个字节,所以它首先排在第一组块的第一个格子里面,第二个是Int类型,它占用4个字节,第一组块已经用掉一格,还剩3格,肯定是无法放下第二Int类型的,因为要考虑到对齐,所以不得不把它放到第二个组块,第三个类型是Char类型,跟第一个类似。所因为有内存分块对齐,我们的内存就不是8个格子了,而是12个了

当数组作为函数的参数传递时,该数组自动退化为同类型的指针。

如void Funct(char a[100])

{

cout<<sizeof(a)<<endl;//输出结果为4

}

而对于

struct



char a;

double b;

char c;



这里内存默认对齐字节数是8字节,所以结构体所占的字节数是24.

深入理解字节对齐:

结构体是种复合数据类型,其成员由基本数据类型构成(short,int,long,float,double,char),也可以是复合数据类型的数据单元(数组,联合,结构等),编译器为结构的每个成员按自然边界分配空间 ,各个成员按照它们被声明的顺序在内存中顺序存储,为了使cpu对变量加快访问,变量的起始地址应该具有某种特性,即所谓的对齐,如4字节的int型,其起始地址应该位于4字节的边界上,即能够被4整除。

字节对齐的作用:便于cpu快速访问,利用字节对齐合理的节省存储空间

对于32位机器来说,4字节对齐能够使cpu的访问速度提高,如果跨越了4字节边界存储,那么cpu就要读取2次,效率降低了。如果在32bit中使用1字节或2字节对齐,反而使处理器 速度降低了。所以要考虑处理器的类型。另外,也要考虑 编译器的类型,vc,gcc默认都是4字节对齐

更改c编译器的缺省字节对齐方式:

缺省条件下,c编译器为每个变量或数据单元按自然边界条件分配空间

1.使用伪指令:#program pack(n)//c编译器按n个字节对齐

#program pack()//取消自定义字节对齐方式

2._attribute(alligned(n)),//让所有的结构成员对齐在n字节的自然边界上,如果结构中有 成员的长 度大于n,则按最大成员的长度来对齐

_attribute_((packed)),//取消编译过程的优化对齐,按实际占用字节数对齐。

举例说明:

struct



char a;

short b;

float c;

char d;



编译器默认情况下对结构体做自然边界对齐,结构的第一个成员a,其偏移地址为0,占用 1个字节,第二个成员为b,其起始地址必须2字节对界。因此编译器在a和b之间填充一个空字节,结构的第3个成员和第4个成员恰好落在自然边界上,在结构中,第3个成员c要求4字节对齐,为该结构中所有成员要求的最大边界单元,因而该结构的自然边界对界条件是4字节,整个结构所占空间为12字节

如添加#program pack(1),整个结构所占字节为8字节

#program pack (2),。。。。。。。。。10字节

32位机器上各个基本数据类型所占的长度:

char 1 (有符号无符号相同)

short 2 (有符号无符号相同)

int 4 (有符号无符号相同)

long 4 (有符号无符号相同)

float 4

double 8

编译器按什么样的原则对齐:

首先看一下4个基本概念,

1.数据自身对齐值:char 1,short 2,int long float 4

2.结构体或类的自身对齐值:其成员中自身对齐值最大的那个

3.指定对齐值:#program pack(value) 对齐值为value

4.数据成员,结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个

有效对齐值N是最终决定数据存储方式的值。有效对齐N,表示“对齐在N上”,也就是说该数据的起始地址%N=0.而数据结构中的数据变量都是按定义的顺序来排放的,结构体的成员要对齐,结构题本身也要根据自身的对齐值圆整(就是结构体成员所占的总长度是结构体有效对齐值的整数倍)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: