OC进化C/C++程序员

内存对齐

2018-05-17  本文已影响57人  片片碎

内存对齐

一种提高内存访问速度的策略,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

上一篇 下一篇

猜你喜欢

热点阅读