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

数据结构还有变量等等都需要占有内存,在很多系统中,它都要求内存分配的时候要对齐,这样做的好处就是可以提高访问内存的速度。
#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.而数据结构中的数据变量都是按定义的顺序来排放的,结构体的成员要对齐,结构题本身也要根据自身的对齐值圆整(就是结构体成员所占的总长度是结构体有效对齐值的整数倍)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值