字节对齐

字节对齐

为什么字节对齐?

一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问

为了提高CPU访问内存中的数据的效率在给每个数据变量分配内存空间时,需考虑地址对齐

 

(1)自然对齐:在给数据分配内存空间时,如果各成员数据的空间的起始地址能够被数据的长度整除,结构的总大小是最大sizeof(类型)的整数倍

typedef struct _a 
{
   char c1;
   long i;
   char c2;
   double f;
}a;
typedef struct _b 
{
   char c1;
   char c2;
   long i;
   double f;
}b;

 

结构体a的长度为24c1一个字节,i四个字节,为了对齐,C1要补齐3个字节,C2一个字节,f八个字节,为了对齐,C2要补齐3个字节,这里一共20个字节,因为总长度要是最大sizeofdouble)的倍数,所以要为24个字节

结构体b的长度为16c1一个字节,C2一个字节,补齐2字节,i四个字节,f八个字节,一共为16个字节,也是8的倍数

 

(2)适当对齐:在给数据分配内存空间时,如果数据的空间的起始地址能被数据的M值整除,结构的总大小是M值的整数倍

 对于不同的数据都存在一个M

 当数据的长度<机器字长  M=数据长度

 当数据的长度>机器字长  M=机器字长

 

基本数据:长度对齐

数组:     以元素的M值对齐

指针:     4字节对齐

联合体:   成员中最大的M值对齐

结构体:   成员中最大的M值(成员排序不同,所占内存大小不一样)

struct A{

    char x;

    int y;

    short z;  

}st1;

struct B{

    char x;

    short z;  

    int y;

}st2;

 

结构体A总长度为12,首先看M值,最大的是y,四个字节,未超过机器字节,所以M4x一个字节,补齐3字节,y四个字节,z两个字节,补齐2字节,一共12字节,M的倍数

结构体B总长度为8M值也是为4x一个字节,z两个个字节,补齐一个字节,y四个字节,一共8个字节,是M的倍数

 

从上面可以看到,结构体成员是一样的,但是顺序不一样,导致了占用的空间不一样,所以我们在定义结构体成员时,最好是按字节长度从小到大定义,可以节省空间

 

(3)栈上对齐:函数内的变量一般都是存在栈上的,x86平台是四字节对齐,x64平台是16字节对齐

Void test(void) 

    char c =0; 
    int a = 4; 
    char str[10]= "hello"; 
    float f = 2.0f; 

f = a+c;
}

占用空间是24字节,c一个字节,补齐3字节,a四个字节,str10个字节,补齐2字节,f四个字节,一共24字节

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2019-04-07 12:13  jemyyy  阅读(506)  评论(0编辑  收藏  举报