2018/5/18 15:04:11当前位置推荐好文程序员浏览文章

内存对齐

一种提高内存访问速度的策略,cpu在访问未对其的内存需要经过两次内存访问,而经过内存对齐一次即可以了。


内存对齐系数

每个特定平台上的编译器都有自己的默认“对齐系数”(32位机一般为4,64位机一般为8),通常为4或者8的倍数,

设置对齐参数: #pragma pack(n) ,n为对齐系数,不想对齐能设置为1,设置为0,也表示为用默认对齐

取消自己设置字节对齐方式,用默认对齐方式: #pragma pack()


sizeof

它的基本作使用是判断数据类型或者者表达式长度,要注意的是这不是一个函数,而是一个C++中的关键字!字节数的计算在程序编译时进行,而不是在程序执行的过程中才计算出来!


类型的长度与数据成员对齐

char  //1

short //2

int //4

long // 64bit 8 32bit 4

double //8

// 64bit 8 32bit 4



struct或者union成员对齐规则如下:

对齐规则如下:

准则一:存放的首地址偏移量 %  min(当前类型大小,对齐系数) == 0,假设对齐系数为8

            char  size = 1,min = (8,1) = 1,那么存放的首地址能是任意地址 ,即首地址偏移量 %min == 0

          short  size = 2,min = (8,2) = 2,那么存放的首地址能是0,2,4,6…… ,即首地址偏移量 %min == 0

            int      size = 4,min = (8,4) = 4,那么存放的首地址能是0,4,8,12…… ,即首地址偏移量 %min == 0

            double size= 8,min = (8,8) = 8,那么存放的首地址能是0,8,16…… ,即首地址偏移量 %min == 0

            long size= 8,min = (8,8) = 8,那么存放的首地址能是0,8,16…… ,即首地址偏移量 %min == 0(64bit 8,32bit 4)

            long long size= 8,min = (8,4) = 4,但是内存的存储按照4字节来,即即首地址偏移量 %min == 0

              size = 8,min = (8,8) = 8,那么存放的首地址能是0,8,16…… ,即首地址偏移量 %8 == 0 (指针,oid,或者有类型的int,long,char...,都是如此,32bit 4)

            数组,size就是其对应类型的szie,比方char buffer[4],szie =1,min(8,1)= 1

准则二:结构体整体对齐,也称作二次对齐,结构体整体大小 % min(当前类型最大的大小,对齐系数) == 0



例子:

/ void 和指定类型的指针 /

1-1.默认64bit系统,即对齐系数为8,void类型指针

struct {

    char a;

    void b;

    char c;

} myStruct;

printf("sizeof %ld \n char %p\n void %p char %p\n",sizeof(myStruct),&myStruct.a,&myStruct.d,&myStruct.c);

结果:sizeof 24

char  0x1006826b8  //1+7

void 0x1006826c0 //前面需要补齐8的整数倍 8

char    0x1006826c8 //1

1+(7)+8+1 = 17,17%min(8,8) = 1,需要补齐7,17+7 = 24

1-2.默认64bit系统,即对齐系数为8,char类型指针

struct {

    char a;

    char b;

    char c;

} myStruct;

结果:sizeof 24

char  0x1006826b8  //1+7

char 0x1006826c0 //前面需要补齐8的整数倍 8

char    0x1006826c8 //1

1+(7)+8+1 = 17,17%min(8,8) = 1,需要补齐7,17+7 = 24

1-3.默认64bit系统,即对齐系数为8,int类型指针

struct {

    char a;

    int b;

    char c;

} myStruct;

结果:sizeof 24

char  0x1006826b8  //1+7

int 0x1006826c0 //前面需要补齐8的整数倍 8

char    0x1006826c8 //1

1+(7)+8+1 = 17,17%min(8,8) = 1,需要补齐7,17+7 = 24

/ 数组:大小为其类型的大小 /

2-1.默认64bit系统,即设置系数为8

#pragma pack(8)

struct {

    char a;

    int b[6];

    char c;

} myStruct;

结果:sizeof 32

char    0x1006e66b8  //1 +3

  int[]    0x1006e66bc // 4 6 = 24

  char  0x1006e66d4  //1

min = min(8,4) = 4;

1+(3)+24+1 = 29 ,29%4 = 1,需补3  29+3 = 32

2-2.默认64bit系统,即设置系数为8

#pragma pack(8)

struct {

    char a;

    char b[6];

    char c;

} myStruct;

结果:sizeof 32

char    0x1006ba6b8  //1

char[]    0x1006ba6b9 // 1 6 = 6

  char  0x1006ba6bf  //1

min = min(8,8) = 8;

1+6+1 = 8

/ 内存对齐系数设置 /

3-1.默认64bit系统,即设置系数为4

#pragma pack(4)

struct {

    char a;

    int b;

    char c;

} myStruct;

结果:sizeof 12

char 0x1006926b8  //1 +3

  int    0x1006926bc // 4

char 0x1006926c0  //1

min = min(4,4) = 4;

1+(3)+4+1 = 9 ,9%4 = 1,需补3  9+3 = 12

3-2.默认64bit系统,即设置系数为8

#pragma pack(8)

struct {

    char a;

    int b;

    char c;

} myStruct;

结果:sizeof 12

char 0x1006926b8  //1 +3  min (1,8) = 1

  int    0x1006926bc // 4  min (4,8) = 4

char 0x1006926c0  //1  min (1,8) = 1

min = min(8,4) = 4;

1+(3)+4+1 = 9 ,9%4 = 1,需补3  9+3 = 12

/ double 和long /

4-1 long long

#pragma pack(8)

struct {

    char a;

    long long b;

    char c;

} myStruct;

结果:sizeof 24

char 0x1006da6b8

long long  0x1006da6c0

char 0x1006da6c8

4-2 long

#pragma pack(8)

struct {

    char a;

    long b;

    char c;

} myStruct;

结果:sizeof 24

char 0x10068e6b8

long 0x10068e6c0

char 0x10068e6c8

4-3

#pragma pack(8)

struct {

    char a;

    double b;

    char c;

} myStruct;

结果:sizeof 24

char 0x10074a6b8

void 0x10074a6c0

char 0x10074a6c8

网友评论